From patchwork Fri Oct 25 02:26:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99518 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 766F8385840B for ; Fri, 25 Oct 2024 03:35:45 +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 C2B933858D33 for ; Fri, 25 Oct 2024 03:35:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C2B933858D33 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 C2B933858D33 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=1729827306; cv=none; b=wfKvSsJddYOp3a4x9WWLusTFG4aJWFbE2y+PlQQVTNasp5CH3sVh3KwVfOXqWK+icxV9dCRDOW6yjTZgZlG/XEWfDhEGAla0WwOjNZhVtJdNOPtNGBsx8dNlN6Cwa7Ahgttfvdy2CdCdwYfeJOMHl9vU2LaHRBYOpqA10sJia+0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827306; c=relaxed/simple; bh=Tl6MOeGMkfxlNWl06MkA4v24pYKJ0XhjXFpIcIBpI9A=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=seXw8unk+OwsGgymF0PaJwpvxZiDiUVMTdJuKqSzblKBFqyChlImlzkiScjavqkjl38i+oxORkf6sDBfLvvz7ZdRmh/o5oV/NQAV7Wsd0BKSwAZjdhQBHbpTUEEyem26OXw0kmKsvALGvE9D7QsdVFWz6+UDdTnZhXk77kpOzrQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827302; 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=9QP3imvLapmnpdzHYQhZbenIeCxzs81N3tWhHWmdeFI=; b=fQzBDYomdz5akB6w1TLxEsNfB+f7TNhcDLU/jbMKx6mBy/Vfg6KS4Edj6ynK2RXtIPCezv A0m5B8RO7zeREmOBFAIrqcvIclIFb8EMgT05U+3yg+D3PYiZHnIQIZv0rdq2/z/qwPgLkD ed/u5x3tlaAMNubTjd0ZEJe5kbIoPRg= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-463-8_216W5YMFCska5gtKGZsg-1; Thu, 24 Oct 2024 23:35:01 -0400 X-MC-Unique: 8_216W5YMFCska5gtKGZsg-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7249119560B5 for ; Fri, 25 Oct 2024 03:35:00 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 79AC9300018D; Fri, 25 Oct 2024 03:34:59 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 01/11] Don't attempt to find TLS address when target has no registers Date: Thu, 24 Oct 2024 19:26:19 -0700 Message-ID: <20241025033431.36274-2-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 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 fixes two bugs, one of which is Bug 25807 - that one is fixed by the change in findvar.c. I found it while testing on aarch64; it turned a KFAIL for gdb.threads/tls.exp: print a_thread_local into a FAIL due to a GDB internal error. In addition to the existing test just noted, I've also added a test to the new test case gdb.base/tls-nothreads.exp. It'll be tested, using different scenarios, up to 8 times: PASS: gdb.base/tls-nothreads.exp: default: force_internal_tls=false: after exit: print tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: default: force_internal_tls=true: after exit: print tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: static: force_internal_tls=false: after exit: print tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: static: force_internal_tls=true: after exit: print tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: pthreads: force_internal_tls=false: after exit: print tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: pthreads: force_internal_tls=true: after exit: print tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: pthreads-static: force_internal_tls=false: after exit: print tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: pthreads-static: force_internal_tls=true: after exit: print tls_tbss_1 There is a related problem that's fixed by the minsyms.c change. It can be observed when debugging a program without debugging symbols when the program is not executing. I've written a new test for this, but it's included in the new test case gdb.base/tls-nothreads.exp, found later in this series. Depending on the target, it'll be run up to 8 times for different targets. E.g., on aarch64, I'm seeing these PASSes, all of which test this change: PASS: gdb.base/tls-nothreads.exp: default: force_internal_tls=false: stripped: after exit: print (int) tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: default: force_internal_tls=true: stripped: after exit: print (int) tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: static: force_internal_tls=false: stripped: after exit: print (int) tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: static: force_internal_tls=true: stripped: after exit: print (int) tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: pthreads: force_internal_tls=false: stripped: after exit: print (int) tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: pthreads: force_internal_tls=true: stripped: after exit: print (int) tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: pthreads-static: force_internal_tls=false: stripped: after exit: print (int) tls_tbss_1 PASS: gdb.base/tls-nothreads.exp: pthreads-static: force_internal_tls=true: stripped: after exit: print (int) tls_tbss_1 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=25807 --- gdb/findvar.c | 7 ++++++- gdb/minsyms.c | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/gdb/findvar.c b/gdb/findvar.c index f7760aa61ca..a530e679c8a 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -485,7 +485,12 @@ language_defn::read_var_value (struct symbol *var, /* Determine address of TLS variable. */ if (obj_section && (obj_section->the_bfd_section->flags & SEC_THREAD_LOCAL) != 0) - addr = target_translate_tls_address (obj_section->objfile, addr); + { + if (!target_has_registers ()) + error (_("Cannot read `%s' without registers"), + var->print_name ()); + addr = target_translate_tls_address (obj_section->objfile, addr); + } } break; diff --git a/gdb/minsyms.c b/gdb/minsyms.c index 33eb9072e5f..a904bd96045 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -1684,7 +1684,13 @@ find_minsym_type_and_address (minimal_symbol *msymbol, { /* Skip translation if caller does not need the address. */ if (address_p != NULL) - *address_p = target_translate_tls_address (objfile, addr); + { + if (!target_has_registers ()) + error (_( + "Cannot determine address of TLS symbol `%s' without registers"), + bound_msym.minsym->print_name ()); + *address_p = target_translate_tls_address (objfile, addr); + } return builtin_type (objfile)->nodebug_tls_symbol; } From patchwork Fri Oct 25 02:26:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99519 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 14BFC3858C39 for ; Fri, 25 Oct 2024 03:36:13 +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 113F73858D34 for ; Fri, 25 Oct 2024 03:35:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 113F73858D34 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 113F73858D34 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=1729827307; cv=none; b=KC45Gg7l3GvGSJyEdZzbpzk7bPSI0bV7obs8CRSwhlN5xFAaOfeJtuYcKHxxSDCakQhrMooKxskGzSIVMQkdNSQyhAA75ZxK1PZXKZvfPiy/tmqzgbcfnk+wzETJSStFwipJGHu8bSf9FaExhDxm+X3k6ePlaO+EjbwMDqRk9zI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827307; c=relaxed/simple; bh=/xjatM3GzKfdNWlq4ZVSQ25BA7TIBI1LImJcEUh3JmU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=yCs7EsRBxmywGmiTZs54d52wx/qFOVplsF0YtlSZ/UfHkvf/Sr3haYpVjk6ZNXaZunoqaZE8LAC2jgSUlUfOlcmgzN8Q23rUHeZgXEABYpR0ygfAAAAAw5HTDhPZbUYgU22laMw4zePPYB0UY/rRj/x4o6CX5NME73B2gr8MEAQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827303; 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=ibMUVLjAjzoNerlX70etYfgrVfMRAp7rH8ZrL3jAb2Q=; b=Tsxhw5QoeEy59YSywnzYUk0ydrB5V8gxlBYuAKSvTCtGhDzfb+ZylYPFZMNZtQzQHfZ8iT IV1zwiR59M3oSvOOntqVNwmg1WaioPOO8FhmntxPth7PtyFjpsMJ2d3WrDOXngCdTidVGh bmQRnPcFfGSENvq8UpIPvXcOX6zyMQg= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-622-rikpg3L8Mba1YP_WNV0ChA-1; Thu, 24 Oct 2024 23:35:02 -0400 X-MC-Unique: rikpg3L8Mba1YP_WNV0ChA-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8C69C19560AD for ; Fri, 25 Oct 2024 03:35:01 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B02933000198; Fri, 25 Oct 2024 03:35:00 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 02/11] Allow TLS access to work in gdb.server/no-thread-db.exp Date: Thu, 24 Oct 2024 19:26:20 -0700 Message-ID: <20241025033431.36274-3-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.9 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 The patches later in the series add GDB-internal TLS support for certain targets. This commit updates the "print foo" test in gdb.server/no-thread-db.exp to accept either a TLS failure (when libthread_db isn't available) or printing the correct answer, which will occur when GDB's internal TLS address resolution can be used. I'm making this change prior to the commits which actually add the GDB-internal TLS support in order to avoid tripping regression testers. --- gdb/testsuite/gdb.server/no-thread-db.exp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gdb/testsuite/gdb.server/no-thread-db.exp b/gdb/testsuite/gdb.server/no-thread-db.exp index 656fad1a560..baad81b0f8e 100644 --- a/gdb/testsuite/gdb.server/no-thread-db.exp +++ b/gdb/testsuite/gdb.server/no-thread-db.exp @@ -57,6 +57,8 @@ gdb_breakpoint ${srcfile}:[gdb_get_line_number "after tls assignment"] gdb_continue_to_breakpoint "after tls assignment" # Printing a tls variable should fail gracefully without a libthread_db. +# Alternately, the correct answer might be printed due GDB's internal +# TLS support for some targets. set re_exec "\[^\r\n\]*[file tail $binfile]" gdb_test "print foo" \ - "Cannot find thread-local storage for Thread \[^,\]+, executable file $re_exec:\[\r\n\]+Remote target failed to process qGetTLSAddr request" + "= 1|(?:Cannot find thread-local storage for Thread \[^,\]+, executable file $re_exec:\[\r\n\]+Remote target failed to process qGetTLSAddr request)" From patchwork Fri Oct 25 02:26:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99528 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 A44E43858435 for ; Fri, 25 Oct 2024 03:39:14 +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 C02253858D39 for ; Fri, 25 Oct 2024 03:35:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C02253858D39 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 C02253858D39 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=1729827326; cv=none; b=cutvC7FfOTlWGATaVlQt2OZ5EDbp6HeH+lTWfI1X6qqbJtd6sPNnyks/zSYawfuIyWmwHm7iXIhkZWJkX5IZbvmUCY8Qu1LddbAHbQtT+0sUSUd+ZFdHa5gJXcL5jAt27u0UOiE32HsHrhLo/IZ1CiX6Fq6LUbuusnIfc2aOigk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827326; c=relaxed/simple; bh=3zNcUMD7chDJsNWef7nLJ1nWvJEVxHuHTAQVb5B2e4k=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Lu0Qe2yz9L2m0zMR3C99csdQAWz9yEalKAF1P1D0tF5Kh92T95cxkDa329P8KgjfJZMxEOTJkuPGzYSxL0wL3u/7DAmNL9MlVtGhlmhMtQ+YCy7tG/8tKEweV3qExSAzusznEl0RYvTx4a5mPDmLK0mbQ+7SurQtfr5LV15UHJA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827315; 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=G1qOjXhN6MVrHNXAPw8XEMh5mU4qG+qGot/jjb9gdDk=; b=Z7HcdGquCejBIgDemUem1AKz4Tb27gUsUiPLpKyq+eCm+5SeW2KyIjDDNy4mUPK/QSeOjk +j6ih9kUHak8FLNdPCWM2VCJ0cgt6JPiOGsTnIpeCpURflUP9miBttx6yBN98L+II0lbZJ 5NH+52/kbP769WTtLslOlDUiFNRALEk= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-100-Gcm_rIknPTmCqrL8bRcCHA-1; Thu, 24 Oct 2024 23:35:04 -0400 X-MC-Unique: Gcm_rIknPTmCqrL8bRcCHA-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C16D91955F41 for ; Fri, 25 Oct 2024 03:35:02 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E92B83000198; Fri, 25 Oct 2024 03:35:01 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 03/11] Track and fetch TLS module ids for MUSL and GLIBC Date: Thu, 24 Oct 2024 19:26:21 -0700 Message-ID: <20241025033431.36274-4-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.0 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 adds, to solib-svr4.h and solib-svr4.c, functions glibc_link_map_to_tls_module_id and musl_link_map_to_tls_module_id for use with callers in linux-tdep.c (which is not in this commit). It adds a number of helper functions for implementing link map to module id support. It also renames existing function 'find_program_interpreter' to 'svr4_find_program_interpreter' and makes it visible to other source files within GDB. It will be used in the libc sniffing code in linux-tdep.c in a later commit in this series. The libc sniffer is needed in order to know which link map to module id function to call as the method for determining module ids differs between libc / dynamic linker implementations. These details are discussed in comments in the patch. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24548 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31563 --- gdb/solib-svr4.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++- gdb/solib-svr4.h | 12 +++ 2 files changed, 211 insertions(+), 4 deletions(-) diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 7999a8e6c7e..b331aac6122 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -405,6 +405,9 @@ struct svr4_info The special entry zero is reserved for a linear list to support gdbstubs that do not support namespaces. */ std::map> solib_lists; + + bool glibc_tls_slots_inited = false; + std::vector glibc_tls_slots; }; /* Per-program-space data key. */ @@ -586,10 +589,10 @@ read_program_header (int type, int *p_arch_size, CORE_ADDR *base_addr) return buf; } +/* See solib-svr4.h. */ -/* Return program interpreter string. */ -static std::optional -find_program_interpreter (void) +std::optional +svr4_find_program_interpreter () { /* If we have a current exec_bfd, use its section table. */ if (current_program_space->exec_bfd () @@ -1516,6 +1519,194 @@ svr4_fetch_objfile_link_map (struct objfile *objfile) return 0; } +/* Return true if bfd section BFD_SECT is a thread local section + (i.e. either named ".tdata" or ".tbss"), and false otherwise. */ + +static bool +is_thread_local_section (struct bfd_section *bfd_sect) +{ + return ((strcmp (bfd_sect->name, ".tdata") == 0 + || strcmp (bfd_sect->name, ".tbss") == 0) + && bfd_sect->size != 0); +} + +/* Return true if objfile OBJF contains a thread local section, and + false otherwise. */ + +static bool +has_thread_local_section (const objfile *objf) +{ + for (obj_section *objsec : objf->sections ()) + if (is_thread_local_section (objsec->the_bfd_section)) + return true; + return false; +} + +/* Return true if solib SO contains a thread local section, and false + otherwise. */ + +static bool +has_thread_local_section (const solib &so) +{ + for (const target_section &p : so.sections) + if (is_thread_local_section (p.the_bfd_section)) + return true; + return false; +} + +/* For the MUSL C library, given link map address LM_ADDR, return the + corresponding TLS module id, or 0 if not found. + + Background: Unlike the mechanism used by glibc (see below), the + scheme used by the MUSL C library is pretty simple. If the + executable contains TLS variables it gets module id 1. Otherwise, + the first shared object loaded which contains TLS variables is + assigned to module id 1. TLS-containing shared objects are then + assigned consecutive module ids, based on the order that they are + loaded. When unloaded via dlclose, module ids are reassigned as if + that module had never been loaded. */ + +int +musl_link_map_to_tls_module_id (CORE_ADDR lm_addr) +{ + /* When lm_addr is zero, the program is statically linked. Any TLS + variables will be in module id 1. */ + if (lm_addr == 0) + return 1; + + int mod_id = 0; + if (has_thread_local_section (current_program_space->symfile_object_file)) + mod_id++; + + struct svr4_info *info = get_svr4_info (current_program_space); + + /* Cause svr4_current_sos() to be run if it hasn't been already. */ + if (info->main_lm_addr == 0) + solib_add (NULL, 0, auto_solib_add); + + /* Handle case where lm_addr corresponds to the main program. + Return value is either 0, when there are no TLS variables, or 1, + when there are. */ + if (lm_addr == info->main_lm_addr) + return mod_id; + + /* Iterate through the shared objects, possibly incrementing the + module id, and returning mod_id should a match be found. */ + for (const solib &so : current_program_space->solibs ()) + { + if (has_thread_local_section (so)) + mod_id++; + + auto *li = gdb::checked_static_cast (so.lm_info.get ()); + if (li->lm_addr == lm_addr) + return mod_id; + } + return 0; +} + +/* For GLIBC, given link map address LM_ADDR, return the corresponding TLS + module id, or 0 if not found. */ + +int +glibc_link_map_to_tls_module_id (CORE_ADDR lm_addr) +{ + /* When lm_addr is zero, the program is statically linked. Any TLS + variables will be in module id 1. */ + if (lm_addr == 0) + return 1; + + /* Look up lm_addr in the TLS slot data structure. */ + struct svr4_info *info = get_svr4_info (current_program_space); + auto it = std::find (info->glibc_tls_slots.begin (), + info->glibc_tls_slots.end (), + lm_addr); + if (it == info->glibc_tls_slots.end ()) + return 0; + else + return 1 + it - info->glibc_tls_slots.begin (); +} + +/* Conditionally, based on whether the shared object, SO, contains TLS + variables, assign a link map address to a TLS module id slot. This + code is GLIBC-specific and may only work for specific GLIBC + versions. That said, it is known to work for (at least) GLIBC + versions 2.27 thru 2.40. + + Background: In order to implement internal TLS address lookup + code, it is necessary to find the module id that has been + associated with a specific link map address. In GLIBC, the TLS + module id is stored in struct link_map, in the member + 'l_tls_modid'. While the first several members of struct link_map + are part of the SVR4 ABI, the offset to l_tls_modid definitely is + not. Therefore, since we don't know the offset to l_tls_modid, we + cannot simply look it up - which is a shame, because things would + be so much more easy and obviously accurate, if we could access + l_tls_modid. + + GLIBC has a concept of TLS module id slots. These slots are + allocated consecutively as shared objects containing TLS variables + are loaded. When unloaded (e.g. via dlclose()), the corresponding + slot is marked as unused, but may be used again when later loading + a shared object. + + The functions tls_maybe_fill_slot and tls_maybe_erase_slot are + associated with the observers 'solib_loaded' and 'solib_unloaded'. + They (attempt to) track use of TLS module id slots in the same way + that GLIBC does, which will hopefully provide an accurate module id + when asked to provide it via glibc_link_map_to_tls_module_id(), + above. */ + +static void +tls_maybe_fill_slot (solib &so) +{ + struct svr4_info *info = get_svr4_info (current_program_space); + if (!info->glibc_tls_slots_inited) + { + /* Cause svr4_current_sos() to be run if it hasn't been already. */ + if (info->main_lm_addr == 0) + svr4_current_sos_direct (info); + + /* Quit early when main_lm_addr is still 0. */ + if (info->main_lm_addr == 0) + return; + + /* Also quit early when symfile_object_file is not yet known. */ + if (current_program_space->symfile_object_file == nullptr) + return; + + if (has_thread_local_section (current_program_space->symfile_object_file)) + info->glibc_tls_slots.push_back (info->main_lm_addr); + info->glibc_tls_slots_inited = true; + } + + if (has_thread_local_section (so)) + { + auto it = std::find (info->glibc_tls_slots.begin (), + info->glibc_tls_slots.end (), + 0); + auto *li = gdb::checked_static_cast (so.lm_info.get ()); + if (it == info->glibc_tls_slots.end ()) + info->glibc_tls_slots.push_back (li->lm_addr); + else + *it = li->lm_addr; + } +} + +/* Remove a link map address from the TLS module slot data structure. + As noted above, this code is GLIBC-specific. */ + +static void +tls_maybe_erase_slot (program_space *pspace, const solib &so) +{ + struct svr4_info *info = get_svr4_info (pspace); + auto *li = gdb::checked_static_cast (so.lm_info.get ()); + auto it = std::find (info->glibc_tls_slots.begin (), + info->glibc_tls_slots.end (), + li->lm_addr); + if (it != info->glibc_tls_slots.end ()) + *it = 0; +} + /* On some systems, the only way to recognize the link map entry for the main executable file is by looking at its name. Return non-zero iff SONAME matches one of the known main executable names. */ @@ -2305,7 +2496,7 @@ enable_break (struct svr4_info *info, int from_tty) /* Find the program interpreter; if not found, warn the user and drop into the old breakpoint at symbol code. */ std::optional interp_name_holder - = find_program_interpreter (); + = svr4_find_program_interpreter (); if (interp_name_holder) { const char *interp_name = (const char *) interp_name_holder->data (); @@ -3382,4 +3573,8 @@ _initialize_svr4_solib () { gdb::observers::free_objfile.attach (svr4_free_objfile_observer, "solib-svr4"); + + /* Set up observers for tracking GLIBC TLS module id slots. */ + gdb::observers::solib_loaded.attach (tls_maybe_fill_slot, "solib-svr4"); + gdb::observers::solib_unloaded.attach (tls_maybe_erase_slot, "solib-svr4"); } diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h index 579fe6d9843..6e25441f221 100644 --- a/gdb/solib-svr4.h +++ b/gdb/solib-svr4.h @@ -112,4 +112,16 @@ extern struct link_map_offsets *svr4_lp64_fetch_link_map_offsets (void); SVR4 run time loader. */ int svr4_in_dynsym_resolve_code (CORE_ADDR pc); +/* For the MUSL C library, given link map address LM_ADDR, return the + corresponding TLS module id, or 0 if not found. */ +int musl_link_map_to_tls_module_id (CORE_ADDR lm_addr); + +/* For GLIBC, given link map address LM_ADDR, return the corresponding TLS + module id, or 0 if not found. */ +int glibc_link_map_to_tls_module_id (CORE_ADDR lm_addr); + +/* Return program interpreter string. */ + +std::optional svr4_find_program_interpreter (); + #endif /* solib-svr4.h */ From patchwork Fri Oct 25 02:26:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99520 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 A13DA3858C98 for ; Fri, 25 Oct 2024 03:37:05 +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 946C73858C98 for ; Fri, 25 Oct 2024 03:35:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 946C73858C98 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 946C73858C98 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=1729827314; cv=none; b=GJGVv0WxiSvdvDoHWwCQdfWFwwl75HmAtDiLcLRgpjkec51osX+6ys5fdsDjYCX2Kkb7VJkIpfjsZZtzmgRC6ZSoHYllCTI1IX7q5NtBKBir5Y3EWVVdePm1e2REM1r1AEU2jreVg2m0e4/2UvghtYb+M6hNLtf6JXplom56L7k= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827314; c=relaxed/simple; bh=9uO0xAwQ5a4r5eKLMJeHFxFKyvVOMQZ6Yn658QIy5GQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=QNpOkpupcu4pf/KBCRW0LT9+1z4ohtofxfjzOxXXsheP3Ufg+IJXx5qXqo1re+fIoT8NcWU+g/4J4yPnZk3lALlHQAS9QyObX1PFKtJ8e9J7fFfb0mxeHbbgsaJBCA9CCFlQeI1woRRzkxeU77EWFDjbVKDTm1hwo1AG1y8cE84= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827308; 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=At2m1qq4PNvk5xGxpMVULIQMwdBdK8knw1ihdRzlKgA=; b=dHJwN+tfgNwu4aJlLG1kMGX/aLp82R1efeayd0XP1gdBEg0qy7t/jUkFGS6yOi1Oqt+xOV IBSBdpDlH92cpcU9qJyBrQCoKQ9ZZOQQGmORZUGITo5dTqIfc7jnqrUXiXRkb1zjoWm2Iz j+1KZ+o/OoOm/GnKzd9RLUZ5xT45cKg= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-688-hIRD6CBtMPGPFcGttWI5Xw-1; Thu, 24 Oct 2024 23:35:04 -0400 X-MC-Unique: hIRD6CBtMPGPFcGttWI5Xw-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 039081955F43 for ; Fri, 25 Oct 2024 03:35:04 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2CE4D3000198; Fri, 25 Oct 2024 03:35:02 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 04/11] Implement internal TLS address lookup for Linux targets Date: Thu, 24 Oct 2024 19:26:22 -0700 Message-ID: <20241025033431.36274-5-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.9 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 adds non-architecture-specific support for internal TLS address lookup for Linux targets. By "internal", I mean support which does not rely on libthread_db. Knowledge of how to traverse TLS data structures is contained in this commit along with the next commit containing architecture specific knowledge regarding TLS offsets, registers, and such. The new function 'linux_get_thread_local_address' is a gdbarch method. It should be passed as an argument to set_gdbarch_get_thread_local_address in architecture specific -linux-tdep.c files which wish to offer internal TLS support. The architecture specific tdep files need to define a get_tls_dtv_addr method - as the name suggests, it needs to return the address of the DTV (dynamic thread vector) via architecture specific means. This usually entails fetching the thread pointer via a register or registers assigned to this purpose, and then using that value to locate the address of the DTV from within the TCB (thread control block). Additionally, some architectures also need to provide a DTP offset, which is used by the MUSL C library to adjust the value obtained from a DTV entry to that of the start of the TLS block for a particular thread. This is provided, when necessary, by a get_tls_dtp_offset method. Both methods, get_tls_dtv_addr and get_tls_dtp_offset, are registered with data structures maintained by linux-tdep.c via the new function linux_register_tls_methods(). Thus, for example, on RISC-V, riscv_linux_init_abi() will make the following two calls, the first for registering the internal get_thread_local_address gdbarch method and the second for registering riscv-specific methods for obtaining the DTV address and DTP offset: set_gdbarch_get_thread_local_address (gdbarch, linux_get_thread_local_address); linux_register_tls_methods (info, gdbarch, riscv_linux_get_tls_dtv_addr, riscv_linux_get_tls_dtp_offset); Internal TLS support is provided for two C libraries, GLIBC, and MUSL. Details for accessing the various TLS data structures differ between these libraries. As a consequence, linux-tdep.h defines a new enum, linux_libc, with values linux_libc_unknown, linux_libc_musl, and linux_libc_glibc. A new static function libc_tls_sniffer uses heuristics to (try to) decide whether a program was linked against GLIBC or MUSL. Working out what the heuristics should be, especially for statically linked binaries, turned out to be harder than I thought it would be. A new maintenance setting, force-internal-tls-address-lookup, has been added, which, when set to 'on', will (as the name suggests) force the internal TLS lookup mechanisms to be used. Otherwise, if thread_db support is available (via the thread stratum), that will be preferred since it should be more accurate. I expect that this setting will be mostly used by test cases in the GDB test suite. The new test cases that are part of this series all use it, with iterations using both 'on' and 'off' for all of the tests therein. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24548 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31563 --- gdb/linux-tdep.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++ gdb/linux-tdep.h | 36 ++++++++ 2 files changed, 247 insertions(+) diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 65ec221ef48..42ff1b3f2a1 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -48,6 +48,11 @@ #include #include +/* When true, force internal TLS address lookup instead of lookup via + the thread stratum. */ + +static bool force_internal_tls_address_lookup = false; + /* This enum represents the values that the user can choose when informing the Linux kernel about which memory mappings will be dumped in a corefile. They are described in the file @@ -198,6 +203,15 @@ struct linux_gdbarch_data { struct type *siginfo_type = nullptr; int num_disp_step_buffers = 0; + + /* Method for looking up TLS DTV. */ + get_tls_dtv_addr_ftype *get_tls_dtv_addr = nullptr; + + /* Method for looking up the TLS DTP offset. */ + get_tls_dtp_offset_ftype *get_tls_dtp_offset = nullptr; + + /* Cached libc value for TLS lookup purposes. */ + enum linux_libc libc = linux_libc_unknown; }; static const registry::key @@ -2744,6 +2758,172 @@ show_dump_excluded_mappings (struct ui_file *file, int from_tty, " flag is %s.\n"), value); } +/* For TLS lookup purposes, use heuristics to decide whether program + was linked against MUSL or GLIBC. */ + +static enum linux_libc +libc_tls_sniffer (struct gdbarch *gdbarch) +{ + /* Check for cached libc value. */ + linux_gdbarch_data *gdbarch_data = get_linux_gdbarch_data (gdbarch); + if (gdbarch_data->libc != linux_libc_unknown) + return gdbarch_data->libc; + + linux_libc libc = linux_libc_unknown; + + /* Fetch the program interpreter. */ + std::optional interp_name_holder + = svr4_find_program_interpreter (); + if (interp_name_holder) + { + /* A dynamically linked program linked against MUSL will have a + "ld-musl-" in its interpreter name. (Two examples of MUSL + interpreter names are "/lib/ld-musl-x86_64.so.1" and + "lib/ld-musl-aarch64.so.1".) If it's not found, assume GLIBC. */ + const char *interp_name = (const char *) interp_name_holder->data (); + if (strstr (interp_name, "/ld-musl-") != nullptr) + libc = linux_libc_musl; + else + libc = linux_libc_glibc; + gdbarch_data->libc = libc; + return libc; + } + + /* If there is no interpreter name, it's statically linked. For + programs with TLS data, a program statically linked against MUSL + will have the symbols 'main_tls' and 'builtin_tls'. If both of + these are present, assume that it was statically linked against + MUSL, otherwise assume GLIBC. */ + if (lookup_minimal_symbol (current_program_space, "main_tls").minsym + != nullptr + && lookup_minimal_symbol (current_program_space, "builtin_tls").minsym + != nullptr) + libc = linux_libc_musl; + else + libc = linux_libc_glibc; + gdbarch_data->libc = libc; + return libc; +} + +/* Implement gdbarch method, get_thread_local_address, for architectures + which provide a method for determining the DTV and possibly the DTP + offset. */ + +CORE_ADDR +linux_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, + CORE_ADDR lm_addr, CORE_ADDR offset) +{ + linux_gdbarch_data *gdbarch_data = get_linux_gdbarch_data (gdbarch); + + /* Use the target's get_thread_local_address method when: + + - No method has been provided for finding the TLS DTV. + + or + + - The thread stratum has been pushed (at some point) onto the + target stack, except when 'force_internal_tls_address_lookup' + has been set. + + The idea here is to prefer use of of the target's thread_stratum + method since it should be more accurate. */ + if (gdbarch_data->get_tls_dtv_addr == nullptr + || (find_target_at (thread_stratum) != nullptr + && !force_internal_tls_address_lookup)) + { + struct target_ops *target = current_inferior ()->top_target (); + return target->get_thread_local_address (ptid, lm_addr, offset); + } + else + { + /* Details, found below, regarding TLS layout is for the GNU C + library (glibc) and the MUSL C library (musl), circa 2024. + While some of this layout is defined by the TLS ABI, some of + it, such as how/where to find the DTV pointer in the TCB, is + not. A good source of ABI info for some architectures can be + found in "ELF Handling For Thread-Local Storage" by Ulrich + Drepper. That document is worth consulting even for + architectures not described there, since the general approach + and terminology is used regardless. + + Some architectures, such as aarch64, are not described in + that document, so some details had to ferreted out using the + glibc source code. Likewise, the MUSL source code was + consulted for details which differ from GLIBC. */ + enum linux_libc libc = libc_tls_sniffer (gdbarch); + int mod_id; + if (libc == linux_libc_glibc) + mod_id = glibc_link_map_to_tls_module_id (lm_addr); + else /* Assume MUSL. */ + mod_id = musl_link_map_to_tls_module_id (lm_addr); + if (mod_id == 0) + throw_error (TLS_GENERIC_ERROR, _("Unable to determine TLS module id")); + + /* Use the architecture specific DTV fetcher to obtain the DTV. */ + CORE_ADDR dtv_addr = gdbarch_data->get_tls_dtv_addr (gdbarch, ptid, libc); + + /* In GLIBC, The DTV (dynamic thread vector) is an array of + structs consisting of two fields, the first of which is a + pointer to the TLS block of interest. (The second field is a + pointer that assists with memory management, but that's not + of interest here.) Also, the 0th entry is the generation + number, but although it's a single scalar, the 0th entry is + padded to be the same size as all the rest. Thus each + element of the DTV array is two pointers in size. + + In MUSL, the DTV is simply an array of pointers. The 0th + entry is still the generation number, but contains no padding + aside from that which is needed to make it pointer sized. */ + int m; /* Multiplier, for size of DTV entry. */ + switch (libc) + { + case linux_libc_glibc: + m = 2; + break; + default: + m = 1; + break; + } + + /* Obtain TLS block address. Module ids start at 1, so there's + no need to adjust it to skip over the 0th entry of the DTV, + which is the generation number. */ + CORE_ADDR dtv_elem_addr + = dtv_addr + mod_id * m * (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + if (target_read_memory (dtv_elem_addr, buf.data (), buf.size ()) != 0) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch TLS block address")); + const struct builtin_type *builtin = builtin_type (gdbarch); + CORE_ADDR tls_block_addr = gdbarch_pointer_to_address + (gdbarch, builtin->builtin_data_ptr, + buf.data ()); + + /* When the TLS block addr is 0 or -1, this usually indicates that + the TLS storage hasn't been allocated yet. (In GLIBC, some + architectures use 0 while others use -1.) */ + if (tls_block_addr == 0 || tls_block_addr == (CORE_ADDR) -1) + throw_error (TLS_NOT_ALLOCATED_YET_ERROR, _("TLS not allocated yet")); + + /* MUSL (and perhaps other C libraries, though not GLIBC) have + TLS implementations for some architectures which, for some + reason, have DTV entries which must be negatively offset by + DTP_OFFSET in order to obtain the TLS block address. + DTP_OFFSET is a constant in the MUSL sources - these offsets, + when they're non-zero, seem to be either 0x800 or 0x8000, + and are present for riscv[32/64], powerpc[32/64], m68k, and + mips. + + Use the architecture specific get_tls_dtp_offset method, if + present, to obtain this offset. */ + ULONGEST dtp_offset + = gdbarch_data->get_tls_dtp_offset == nullptr + ? 0 + : gdbarch_data->get_tls_dtp_offset (gdbarch, ptid, libc); + + return tls_block_addr - dtp_offset + offset; + } +} + /* To be called from the various GDB_OSABI_LINUX handlers for the various GNU/Linux architectures and machine types. @@ -2787,6 +2967,20 @@ linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); } +/* See linux-tdep.h. */ + +void +linux_register_tls_methods (struct gdbarch_info info, struct gdbarch *gdbarch, + get_tls_dtv_addr_ftype *get_tls_dtv_addr, + get_tls_dtp_offset_ftype *get_tls_dtp_offset) +{ + gdb_assert (get_tls_dtv_addr != nullptr); + + linux_gdbarch_data *gdbarch_data = get_linux_gdbarch_data (gdbarch); + gdbarch_data->get_tls_dtv_addr = get_tls_dtv_addr; + gdbarch_data->get_tls_dtp_offset = get_tls_dtp_offset; +} + void _initialize_linux_tdep (); void _initialize_linux_tdep () @@ -2822,6 +3016,23 @@ VM_DONTDUMP flag (\"dd\" in /proc/PID/smaps) when generating the corefile. For\ more information about this file, refer to the manpage of proc(5) and core(5)."), NULL, show_dump_excluded_mappings, &setlist, &showlist); + + add_setshow_boolean_cmd ("force-internal-tls-address-lookup", class_obscure, + &force_internal_tls_address_lookup, _("\ +Set to force internal TLS address lookup."), _("\ +Show whether GDB is forced to use internal TLS address lookup."), _("\ +When resolving addresses for TLS (Thread Local Storage) variables,\n\ +GDB will attempt to use facilities provided by the thread library (i.e.\n\ +libthread_db). If those facilities aren't available, GDB will fall\n\ +back to using some internal (to GDB), but possibly less accurate\n\ +mechanisms to resolve the addresses for TLS variables. When this flag\n\ +is set, GDB will force use of the fall-back TLS resolution mechanisms.\n\ +This flag is used by some GDB tests to ensure that the internal fallback\n\ +code is exercised and working as expected. The default is to not force\n\ +the internal fall-back mechanisms to be used."), + NULL, NULL, + &maintenance_set_cmdlist, + &maintenance_show_cmdlist); } /* Fetch (and possibly build) an appropriate `link_map_offsets' for diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h index 66b03cabaa6..83f1538f033 100644 --- a/gdb/linux-tdep.h +++ b/gdb/linux-tdep.h @@ -88,6 +88,35 @@ extern void linux_displaced_step_restore_all_in_ptid (inferior *parent_inf, extern void linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, int num_disp_step_buffers); +/* C library variants for TLS lookup. */ + +enum linux_libc +{ + linux_libc_unknown, + linux_libc_musl, + linux_libc_glibc +}; + +/* Function type for "get_tls_dtv_addr" method. */ + +typedef CORE_ADDR (get_tls_dtv_addr_ftype) (struct gdbarch *gdbarch, + ptid_t ptid, + enum linux_libc libc); + +/* Function type for "get_tls_dtp_offset" method. */ + +typedef CORE_ADDR (get_tls_dtp_offset_ftype) (struct gdbarch *gdbarch, + ptid_t ptid, + enum linux_libc libc); + +/* Register architecture specific methods for fetching the TLS DTV + and TLS DTP, used by linux_get_thread_local_address. */ + +extern void linux_register_tls_methods + (struct gdbarch_info info, struct gdbarch *gdbarch, + get_tls_dtv_addr_ftype *get_tls_dtv_addr, + get_tls_dtp_offset_ftype *get_tls_dtp_offset = nullptr); + extern int linux_is_uclinux (void); /* Fetch the AT_HWCAP entry from auxv data AUXV. Use TARGET and GDBARCH to @@ -117,4 +146,11 @@ extern CORE_ADDR linux_get_hwcap2 (); extern struct link_map_offsets *linux_ilp32_fetch_link_map_offsets (); extern struct link_map_offsets *linux_lp64_fetch_link_map_offsets (); +/* Used as a gdbarch method for get_thread_local_address when the tdep + file also defines a suitable method for obtaining the TLS DTV. + See linux_init_abi(), above. */ +CORE_ADDR +linux_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, + CORE_ADDR lm_addr, CORE_ADDR offset); + #endif /* linux-tdep.h */ From patchwork Fri Oct 25 02:26:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99523 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 9A5483858423 for ; Fri, 25 Oct 2024 03:38:20 +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 DC23B3858C53 for ; Fri, 25 Oct 2024 03:35:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DC23B3858C53 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 DC23B3858C53 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=1729827319; cv=none; b=Z8KWqocPKoQx9JWJUSRr9XcP4vytLfas4Vzb9+CXbPmRiKlKfOOuL9OyvDLj+RJsP7Mvj/iw8qoSPQZlNjlP8jcCMRExUXIe7LvCzGluWSc4nXIcdeHSgbGqLoMp4RUdWQTWebCfO+cHCeurZ45wwytAk9QGzOKcbxvbk+2gwU8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827319; c=relaxed/simple; bh=E9qwXdyo9iqcuCUnrjF2p+I3/O/JfxIs8lNqa6ntaEg=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Y+DzBpzYgG2sFOSEdZv9ksUlfgXSVk1Po1mSvGCsq8oN4Ixln9QRNFPMhRV8aFYybnj5+snIQOIzKNdNSu8E9S9nVZj/Y3pdpAgGwwcNn/cCMXfkWh7eZcNpUAeAIQn5MFn+TYm9KE8Emsz6ItUuz10o8Qfd3+qM5Cey2oqoEqQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827308; 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=0i/w5Vbpc23AnxbFg15QXqxTs+MJG/1c55biK/4pL1E=; b=KFW2UNbVKanJ5O/qi4tWWtDKFE+iMGn7uelpCFAEeeN1x+KswsdG0t7pYKDvGguO2/2nOj rB0bECVuNLujj15AsKnNFiWpfNSfQtvS1A44oLyx+60XE4wfXosKQEk15D4DdXaj12lnC0 pzFoLn32NL5N1Mk3F0uI5ME5oqfvlWc= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-116-Cmbog7RvOXikIiTcxDhreQ-1; Thu, 24 Oct 2024 23:35:07 -0400 X-MC-Unique: Cmbog7RvOXikIiTcxDhreQ-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0B1E51955F43; Fri, 25 Oct 2024 03:35:06 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 62705300018D; Fri, 25 Oct 2024 03:35:04 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner , Luis Machado Subject: [PATCH v3 05/11] Internal TLS support for aarch64, x86_64, riscv, ppc64, and s390x Date: Thu, 24 Oct 2024 19:26:23 -0700 Message-ID: <20241025033431.36274-6-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.0 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 For each architecture, aarch64, x86_64, riscv, ppc64, and s390x, this commit defines a suitable 'get_tls_dtv_addr' method and, when necessary, a 'get_tls_dtp_offset' method. It also registers linux_get_thread_local_address, defined in linux-tdep.c (in an earlier commit), as the get_thread_local_address gdbarch method. It also registers its architecture specific code using linux_register_tls_methods(). Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24548 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31563 Reviewed-By: Luis Machado --- gdb/aarch64-linux-tdep.c | 55 ++++++++++++++++++++++++++++ gdb/amd64-linux-tdep.c | 37 +++++++++++++++++++ gdb/ppc-linux-tdep.c | 62 ++++++++++++++++++++++++++++++++ gdb/riscv-linux-tdep.c | 78 ++++++++++++++++++++++++++++++++++++++++ gdb/s390-linux-tdep.c | 43 ++++++++++++++++++++++ 5 files changed, 275 insertions(+) diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index c608a84bc71..89423a233f2 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -35,6 +35,7 @@ #include "target/target.h" #include "expop.h" #include "auxv.h" +#include "inferior.h" #include "regcache.h" #include "regset.h" @@ -2693,6 +2694,57 @@ aarch64_use_target_description_from_corefile_notes (gdbarch *gdbarch, return true; } +/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID. + Throw a suitable TLS error if something goes wrong. */ + +static CORE_ADDR +aarch64_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid, + linux_libc libc) +{ + /* On aarch64, the thread pointer is found in the TPIDR register. + Note that this is the first register in the TLS feature - see + features/aarch64-tls.c - and it will always be present. */ + regcache *regcache + = get_thread_arch_regcache (current_inferior (), ptid, gdbarch); + aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + target_fetch_registers (regcache, tdep->tls_regnum_base); + ULONGEST thr_ptr; + if (regcache->cooked_read (tdep->tls_regnum_base, &thr_ptr) != REG_VALID) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer")); + + CORE_ADDR dtv_ptr_addr; + switch (libc) + { + case linux_libc_musl: + /* MUSL: The DTV pointer is found at the very end of the pthread + struct which is located *before* the thread pointer. I.e. + the thread pointer will be just beyond the end of the struct, + so the address of the DTV pointer is found one pointer-size + before the thread pointer. */ + dtv_ptr_addr = thr_ptr - (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + break; + case linux_libc_glibc: + /* GLIBC: The thread pointer (tpidr) points at the TCB (thread control + block). On aarch64, this struct (tcbhead_t) is defined to + contain two pointers. The first is a pointer to the DTV and + the second is a pointer to private data. So the DTV pointer + address is the same as the thread pointer. */ + dtv_ptr_addr = thr_ptr; + break; + default: + throw_error (TLS_GENERIC_ERROR, _("Unknown aarch64 C library")); + break; + } + gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + if (target_read_memory (dtv_ptr_addr, buf.data (), buf.size ()) != 0) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch DTV address")); + + const struct builtin_type *builtin = builtin_type (gdbarch); + CORE_ADDR dtv_addr = gdbarch_pointer_to_address + (gdbarch, builtin->builtin_data_ptr, buf.data ()); + return dtv_addr; +} + static void aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -2714,6 +2766,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); + set_gdbarch_get_thread_local_address (gdbarch, + linux_get_thread_local_address); + linux_register_tls_methods (info, gdbarch, aarch64_linux_get_tls_dtv_addr); /* Shared library handling. */ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 77de8211d86..7512448d987 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -34,6 +34,7 @@ #include "i386-linux-tdep.h" #include "linux-tdep.h" #include "gdbsupport/x86-xstate.h" +#include "inferior.h" #include "amd64-tdep.h" #include "solib-svr4.h" @@ -1767,6 +1768,39 @@ amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch, } } +/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID. + Throw a suitable TLS error if something goes wrong. */ + +static CORE_ADDR +amd64_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid, + enum linux_libc libc) +{ + /* On x86-64, the thread pointer is found in the fsbase register. */ + regcache *regcache + = get_thread_arch_regcache (current_inferior (), ptid, gdbarch); + target_fetch_registers (regcache, AMD64_FSBASE_REGNUM); + ULONGEST fsbase; + if (regcache->cooked_read (AMD64_FSBASE_REGNUM, &fsbase) != REG_VALID) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer")); + + /* The thread pointer (fsbase) points at the TCB (thread control + block). The first two members of this struct are both pointers, + where the first will be a pointer to the TCB (i.e. it points at + itself) and the second will be a pointer to the DTV (dynamic + thread vector). There are many other fields too, but the one + we care about here is the DTV pointer. Compute the address + of the DTV pointer, fetch it, and convert it to an address. */ + CORE_ADDR dtv_ptr_addr = fsbase + gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + if (target_read_memory (dtv_ptr_addr, buf.data (), buf.size ()) != 0) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch DTV address")); + + const struct builtin_type *builtin = builtin_type (gdbarch); + CORE_ADDR dtv_addr = gdbarch_pointer_to_address + (gdbarch, builtin->builtin_data_ptr, buf.data ()); + return dtv_addr; +} + static void amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch, int num_disp_step_buffers) @@ -1797,6 +1831,9 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch, /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); + set_gdbarch_get_thread_local_address (gdbarch, + linux_get_thread_local_address); + linux_register_tls_methods (info, gdbarch, amd64_linux_get_tls_dtv_addr); /* GNU/Linux uses SVR4-style shared libraries. */ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 8a5eea765c2..42a4bc71263 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -2070,6 +2070,63 @@ ppc64_linux_gcc_target_options (struct gdbarch *gdbarch) return ""; } +/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID. + Throw a suitable TLS error if something goes wrong. */ + +static CORE_ADDR +ppc64_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid, + enum linux_libc libc) +{ + /* On ppc64, the thread pointer is found in r13. Fetch this + register. */ + regcache *regcache + = get_thread_arch_regcache (current_inferior (), ptid, gdbarch); + int thread_pointer_regnum = PPC_R0_REGNUM + 13; + target_fetch_registers (regcache, thread_pointer_regnum); + ULONGEST thr_ptr; + if (regcache->cooked_read (thread_pointer_regnum, &thr_ptr) != REG_VALID) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer")); + + /* The thread pointer (r13) is an address that is 0x7000 ahead of + the *end* of the TCB (thread control block). The field + holding the DTV address is at the very end of the TCB. + Therefore, the DTV pointer address can be found by + subtracting (0x7000+8) from the thread pointer. Compute the + address of the DTV pointer, fetch it, and convert it to an + address. */ + CORE_ADDR dtv_ptr_addr = thr_ptr - 0x7000 - 8; + gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + if (target_read_memory (dtv_ptr_addr, buf.data (), buf.size ()) != 0) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch DTV address")); + + const struct builtin_type *builtin = builtin_type (gdbarch); + CORE_ADDR dtv_addr = gdbarch_pointer_to_address + (gdbarch, builtin->builtin_data_ptr, buf.data ()); + return dtv_addr; +} + +/* For internal TLS lookup, return the DTP offset, which is the offset + to subtract from a DTV entry, in order to obtain the address of the + TLS block. */ + +static ULONGEST +ppc_linux_get_tls_dtp_offset (struct gdbarch *gdbarch, ptid_t ptid, + linux_libc libc) +{ + if (libc == linux_libc_musl) + { + /* This value is DTP_OFFSET, which represents the value to + subtract from the DTV entry. For PPC, it can be found in + MUSL's arch/powerpc64/pthread_arch.h and + arch/powerpc32/pthread_arch.h. (Both values are the same.) + It represents the value to subtract from the DTV entry, once + it has been fetched from the DTV array. */ + return 0x8000; + } + else + return 0; +} + static displaced_step_prepare_status ppc_linux_displaced_step_prepare (gdbarch *arch, thread_info *thread, CORE_ADDR &displaced_pc) @@ -2283,6 +2340,11 @@ ppc_linux_init_abi (struct gdbarch_info info, set_gdbarch_gnu_triplet_regexp (gdbarch, ppc64_gnu_triplet_regexp); /* Set GCC target options. */ set_gdbarch_gcc_target_options (gdbarch, ppc64_linux_gcc_target_options); + /* Internal thread local address support. */ + set_gdbarch_get_thread_local_address (gdbarch, + linux_get_thread_local_address); + linux_register_tls_methods (info, gdbarch, ppc64_linux_get_tls_dtv_addr, + ppc_linux_get_tls_dtp_offset); } set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description); diff --git a/gdb/riscv-linux-tdep.c b/gdb/riscv-linux-tdep.c index ff478cf4c28..31d90a32ce4 100644 --- a/gdb/riscv-linux-tdep.c +++ b/gdb/riscv-linux-tdep.c @@ -25,6 +25,7 @@ #include "tramp-frame.h" #include "trad-frame.h" #include "gdbarch.h" +#include "inferior.h" /* The following value is derived from __NR_rt_sigreturn in from the Linux source tree. */ @@ -173,6 +174,79 @@ riscv_linux_syscall_next_pc (const frame_info_ptr &frame) return pc + 4 /* Length of the ECALL insn. */; } +/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID. + Throw a suitable TLS error if something goes wrong. */ + +static CORE_ADDR +riscv_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid, + linux_libc libc) +{ + /* On RISC-V, the thread pointer is found in TP. */ + regcache *regcache + = get_thread_arch_regcache (current_inferior (), ptid, gdbarch); + int thread_pointer_regnum = RISCV_TP_REGNUM; + target_fetch_registers (regcache, thread_pointer_regnum); + ULONGEST thr_ptr; + if (regcache->cooked_read (thread_pointer_regnum, &thr_ptr) != REG_VALID) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer")); + + CORE_ADDR dtv_ptr_addr; + switch (libc) + { + case linux_libc_musl: + /* MUSL: The DTV pointer is found at the very end of the pthread + struct which is located *before* the thread pointer. I.e. + the thread pointer will be just beyond the end of the struct, + so the address of the DTV pointer is found one pointer-size + before the thread pointer. */ + dtv_ptr_addr + = thr_ptr - (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + break; + case linux_libc_glibc: + /* GLIBC: The thread pointer (TP) points just beyond the end of + the TCB (thread control block). On RISC-V, this struct + (tcbhead_t) is defined to contain two pointers. The first is + a pointer to the DTV and the second is a pointer to private + data. So the DTV pointer address is 16 bytes (i.e. the size of + two pointers) before thread pointer. */ + + dtv_ptr_addr + = thr_ptr - 2 * (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + break; + default: + throw_error (TLS_GENERIC_ERROR, _("Unknown RISC-V C library")); + break; + } + + gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + if (target_read_memory (dtv_ptr_addr, buf.data (), buf.size ()) != 0) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch DTV address")); + + const struct builtin_type *builtin = builtin_type (gdbarch); + CORE_ADDR dtv_addr = gdbarch_pointer_to_address + (gdbarch, builtin->builtin_data_ptr, buf.data ()); + return dtv_addr; +} + +/* For internal TLS lookup, return the DTP offset, which is the offset + to subtract from a DTV entry, in order to obtain the address of the + TLS block. */ + +static ULONGEST +riscv_linux_get_tls_dtp_offset (struct gdbarch *gdbarch, ptid_t ptid, + linux_libc libc) +{ + if (libc == linux_libc_musl) + { + /* This value is DTP_OFFSET in MUSL's arch/riscv64/pthread_arch.h. + It represents the value to subtract from the DTV entry, once + it has been loaded. */ + return 0x800; + } + else + return 0; +} + /* Initialize RISC-V Linux ABI info. */ static void @@ -198,6 +272,10 @@ riscv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); + set_gdbarch_get_thread_local_address (gdbarch, + linux_get_thread_local_address); + linux_register_tls_methods (info, gdbarch, riscv_linux_get_tls_dtv_addr, + riscv_linux_get_tls_dtp_offset); set_gdbarch_iterate_over_regset_sections (gdbarch, riscv_linux_iterate_over_regset_sections); diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c index bc1db550d2e..17055d9f7b5 100644 --- a/gdb/s390-linux-tdep.c +++ b/gdb/s390-linux-tdep.c @@ -40,6 +40,7 @@ #include "target.h" #include "trad-frame.h" #include "xml-syscall.h" +#include "inferior.h" #include "features/s390-linux32v1.c" #include "features/s390-linux32v2.c" @@ -1123,6 +1124,45 @@ s390_init_linux_record_tdep (struct linux_record_tdep *record_tdep, record_tdep->ioctl_FIOQSIZE = 0x545e; } +/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID. + Throw a suitable TLS error if something goes wrong. */ + +static CORE_ADDR +s390_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid, + enum linux_libc libc) +{ + /* On S390, the thread pointer is found in two registers A0 and A1 + (or, using gdb naming, acr0 and acr1) A0 contains the top 32 + bits of the address and A1 contains the bottom 32 bits. */ + regcache *regcache + = get_thread_arch_regcache (current_inferior (), ptid, gdbarch); + target_fetch_registers (regcache, S390_A0_REGNUM); + target_fetch_registers (regcache, S390_A1_REGNUM); + ULONGEST thr_ptr_lo, thr_ptr_hi, thr_ptr; + if (regcache->cooked_read (S390_A0_REGNUM, &thr_ptr_hi) != REG_VALID + || regcache->cooked_read (S390_A1_REGNUM, &thr_ptr_lo) != REG_VALID) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer")); + thr_ptr = (thr_ptr_hi << 32) + thr_ptr_lo; + + /* The thread pointer points at the TCB (thread control block). The + first two members of this struct are both pointers, where the + first will be a pointer to the TCB (i.e. it points at itself) + and the second will be a pointer to the DTV (dynamic thread + vector). There are many other fields too, but the one we care + about here is the DTV pointer. Compute the address of the DTV + pointer, fetch it, and convert it to an address. */ + CORE_ADDR dtv_ptr_addr + = thr_ptr + gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + if (target_read_memory (dtv_ptr_addr, buf.data (), buf.size ()) != 0) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch DTV address")); + + const struct builtin_type *builtin = builtin_type (gdbarch); + CORE_ADDR dtv_addr = gdbarch_pointer_to_address + (gdbarch, builtin->builtin_data_ptr, buf.data ()); + return dtv_addr; +} + /* Initialize OSABI common for GNU/Linux on 31- and 64-bit systems. */ static void @@ -1151,6 +1191,9 @@ s390_linux_init_abi_any (struct gdbarch_info info, struct gdbarch *gdbarch) /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); + set_gdbarch_get_thread_local_address (gdbarch, + linux_get_thread_local_address); + linux_register_tls_methods (info, gdbarch, s390_linux_get_tls_dtv_addr); /* Support reverse debugging. */ set_gdbarch_process_record_signal (gdbarch, s390_linux_record_signal); From patchwork Fri Oct 25 02:26:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99524 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 234AC3858435 for ; Fri, 25 Oct 2024 03:38:31 +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 44C873858C78 for ; Fri, 25 Oct 2024 03:35:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 44C873858C78 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 44C873858C78 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=1729827319; cv=none; b=L90mn7m2M0ydKoiCkP1PJstAcH8TZMbWwJXSLgGRYwm46jhHjPZeTVKz7lU0DOp8NCq5uHsR/sJbnutug19erh3QK5tR3fXWDEypm1bbcCG9mZb5RKfedKvpZCnf1t0chV5qtwF41pZO4IrtdoGzJfiu4pm+uk4C1FhK7s9vGPE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827319; c=relaxed/simple; bh=2QqkLm6bDwRAOSzZITbwve82TIOa+YZXcMvOMLtTaz0=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=xPz4TGqNr2jMsSTKtazQ/k7b2j2RB6KJUTxRZ5QgnFFg4I6MJ8558DvbT6Yau9GX/48x2UaJ8YmQL3Q9JmpNrhE7ifprZZT7xUgErTK2HPSP59TU+p5Q0nBgpLkWiIXZXHDCtCr8lHOmGCftSE2ObK21b8o0ThrPLeaD+tdglUw= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827309; 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=VI5P22AmzOdpr+wG9HWWjsmFqVC9Ff5bAy++P8/+9AY=; b=ZhPBN6wB7YCDMoY4DrZnSYjM5IPyXVWrg2AmA/iYlvMNsWnbsIOWEPCYtuP5Q2GiXiWfdr eTGOehIFJnga+WCRtLSSU8HJQ70HYqI2FRAOcfHEO6JVjbcvGbagsNfsf4kQvFwkvdWDbh bQU9+W0UOOoHBO3bLQv3eZaMxCYJ/Dk= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-88-tUQHWD5bNWWNZlDjFIwCJQ-1; Thu, 24 Oct 2024 23:35:07 -0400 X-MC-Unique: tUQHWD5bNWWNZlDjFIwCJQ-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0F5F3195608A for ; Fri, 25 Oct 2024 03:35:07 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3750C300018D; Fri, 25 Oct 2024 03:35:06 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 06/11] Internal, but disabled, TLS support for i386 Date: Thu, 24 Oct 2024 19:26:24 -0700 Message-ID: <20241025033431.36274-7-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, 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 shows how internal TLS address lookup support could be implemented for the i386 target. Unfortunately, it doesn't work due to I386_GSBASE_REGNUM being unavailable for Linux targets. I looked at trying to access the gsbase register via PTRACE_GET_THREAD_AREA, but did not understand it well enough to finish it. Since the i386 target is much less important than it used to be, I gave up working on it. I don't want to leave this disabled code in our sources, so I will delete it in the next commit, however, this commit will be in our git repo, so it'll be available for someone with sufficient interest in the i386 target to look at. --- gdb/i386-linux-tdep.c | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index 9dec83ac753..8e9ffe984a3 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -753,6 +753,45 @@ i386_linux_displaced_step_copy_insn (struct gdbarch *gdbarch, return closure_; } +#if 0 +/* Disabled because fetching I386_GSBASE_REGNUM causes an internal + error. */ + +/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID. + Throw a suitable TLS error if something goes wrong. */ + +static CORE_ADDR +i386_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid, + enum linux_libc libc) +{ + /* On i386, the thread pointer is found in the gsbase register. */ + regcache *regcache + = get_thread_arch_regcache (current_inferior (), ptid, gdbarch); + target_fetch_registers (regcache, I386_GSBASE_REGNUM); + ULONGEST gsbase; + if (regcache->cooked_read (I386_GSBASE_REGNUM, &gsbase) != REG_VALID) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer")); + + /* The thread pointer (gsbase) points at the TCB (thread control + block). The first two members of this struct are both pointers, + where the first will be a pointer to the TCB (i.e. it points at + itself) and the second will be a pointer to the DTV (dynamic + thread vector). There are many other fields too, but the one + we care about here is the DTV pointer. Compute the address + of the DTV pointer, fetch it, and convert it to an address. */ + CORE_ADDR dtv_ptr_addr + = gsbase + gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + gdb_byte buf[gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT]; + if (target_read_memory (dtv_ptr_addr, buf, sizeof buf) != 0) + throw_error (TLS_GENERIC_ERROR, _("Unable to fetch DTV address")); + + const struct builtin_type *builtin = builtin_type (gdbarch); + CORE_ADDR dtv_addr = gdbarch_pointer_to_address + (gdbarch, builtin->builtin_data_ptr, buf); + return dtv_addr; +} +#endif + static void i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -988,6 +1027,11 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); +#if 0 + set_gdbarch_get_thread_local_address (gdbarch, + linux_get_thread_local_address); + linux_register_tls_methods (info, gdbarch, i386_linux_get_tls_dtv_addr); +#endif /* Core file support. */ set_gdbarch_iterate_over_regset_sections From patchwork Fri Oct 25 02:26:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99521 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 7BE3B385842C for ; Fri, 25 Oct 2024 03:37:56 +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 79D863858CDB for ; Fri, 25 Oct 2024 03:35:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 79D863858CDB 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 79D863858CDB 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=1729827319; cv=none; b=a0WFse9LWfUoh0Al3HZFsUPHjEREHRnrolKUcsp2terq9F2XvKuhnQMTHWb3g32Hmd4IZ+il0Q2NbvmedWWQweyq0UzrIYDdV+Pm95n+A318E0NPL67b1wCFp+rwKDHoQlUF7nBFEsHRMhnPK6G3Y/rOhkk7GiOZmgcdQgwwJJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827319; c=relaxed/simple; bh=1a1lVP45oDwVNMziL3le9cHM9WfPdazlOj54/6ewM7I=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=ifKV5HeT1otptQ//Tw6mnJ8yaNbKsuhGNpzqnSAUqoo26q84uJcdKR2MuZbfNsFX3IO6U63yGZWC3kfRojA4kaFJufcJj1E5op9LI2vVaveHJQ83ccRQmZqjOM81+uaD72ahJ34mLfRLd/FqGJSpryDN+ohidky+WQ/i9Iyo4gQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827310; 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=/J7AJrLYKOfuFiKv47ry3kNrOQen9QeZj7OoeI+Efoo=; b=LU9nV4P9md4YkHFJLRPN+LaLPoaWGRhdWdK5TZy/xs+wdXhfm2biScKyfQ6da+BiP8cUrQ RgmRHMgHkrmjqk4onyyeAcW1Jm+CMn+ky7rVIOPTLanGnoJmzm9aPUcYKzfcMfd3Q3xe4o C2Y+mkySbW4IJCi6bZt8AojsTocylGk= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-347-N79oaOeNNeuxcLnV3NSqOg-1; Thu, 24 Oct 2024 23:35:09 -0400 X-MC-Unique: N79oaOeNNeuxcLnV3NSqOg-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4472E19560AA for ; Fri, 25 Oct 2024 03:35:08 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6C39B300018D; Fri, 25 Oct 2024 03:35:07 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 07/11] Delete disabled i386 internal TLS support Date: Thu, 24 Oct 2024 19:26:25 -0700 Message-ID: <20241025033431.36274-8-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 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 As mentioned in the previous commit, this commit deletes the disabled code which could be used to implement internal TLS support for the i386 target. --- gdb/i386-linux-tdep.c | 44 ------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index 8e9ffe984a3..9dec83ac753 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -753,45 +753,6 @@ i386_linux_displaced_step_copy_insn (struct gdbarch *gdbarch, return closure_; } -#if 0 -/* Disabled because fetching I386_GSBASE_REGNUM causes an internal - error. */ - -/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID. - Throw a suitable TLS error if something goes wrong. */ - -static CORE_ADDR -i386_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid, - enum linux_libc libc) -{ - /* On i386, the thread pointer is found in the gsbase register. */ - regcache *regcache - = get_thread_arch_regcache (current_inferior (), ptid, gdbarch); - target_fetch_registers (regcache, I386_GSBASE_REGNUM); - ULONGEST gsbase; - if (regcache->cooked_read (I386_GSBASE_REGNUM, &gsbase) != REG_VALID) - throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer")); - - /* The thread pointer (gsbase) points at the TCB (thread control - block). The first two members of this struct are both pointers, - where the first will be a pointer to the TCB (i.e. it points at - itself) and the second will be a pointer to the DTV (dynamic - thread vector). There are many other fields too, but the one - we care about here is the DTV pointer. Compute the address - of the DTV pointer, fetch it, and convert it to an address. */ - CORE_ADDR dtv_ptr_addr - = gsbase + gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; - gdb_byte buf[gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT]; - if (target_read_memory (dtv_ptr_addr, buf, sizeof buf) != 0) - throw_error (TLS_GENERIC_ERROR, _("Unable to fetch DTV address")); - - const struct builtin_type *builtin = builtin_type (gdbarch); - CORE_ADDR dtv_addr = gdbarch_pointer_to_address - (gdbarch, builtin->builtin_data_ptr, buf); - return dtv_addr; -} -#endif - static void i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -1027,11 +988,6 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); -#if 0 - set_gdbarch_get_thread_local_address (gdbarch, - linux_get_thread_local_address); - linux_register_tls_methods (info, gdbarch, i386_linux_get_tls_dtv_addr); -#endif /* Core file support. */ set_gdbarch_iterate_over_regset_sections From patchwork Fri Oct 25 02:26:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99522 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 DF1073858289 for ; Fri, 25 Oct 2024 03:37:56 +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 2AA7C3858D35 for ; Fri, 25 Oct 2024 03:35:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2AA7C3858D35 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 2AA7C3858D35 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=1729827319; cv=none; b=eEz8u/qBqAh+zZAfqK/wCJ6NwuOXFf9nDLdAOy5ChvimW8iV2dQsiGa3LoWgoVumSVYoGZ6JqsJl4KZasA5vZIMhqyiVQxS+2ri1YQJcnsh1d0W5mQIT4E7fVFkui78Vq5TcYQBYV49tsA3YSsfcRkgSKMRmpUi3BeFNk8i8cpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827319; c=relaxed/simple; bh=dZ1zNsURK+3mIcXWvQUxmbZqIoOeZxPWk8qztdboL18=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=d4t5e8qYyI4bLHRAemHU/0oWyE+VTGLnvVAkdS2dmXhewPoqahQD4jb3u7Reg8OfsylFpmI5rIBPKvKjhQuVdjF7meXj06RouKOUrsza+v0JN6StH4tgosqhonTsXRwZehjLqQJ1Jl2Xtoqk68TvE+jXJOhhDaVlqi3uqVz+L/8= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827311; 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=bvm7qnE7xV92Vm8FUMsjDrDAWRpO4HGxH12b87tVQEo=; b=H52SPN5ie1nZcx/LI85WSiIP14HbWfQFAMsf0dYkgpEe7mN8u+WyxkufSdAMyJOVEASdwz riR/aH/CkNY+l4SVeW1+Lk1xmY0LlbjJRwOj6I1bUG0p/rrkhixTgsa0GlC+b+SkeDJIMl oIf8AQPGunTVVa93GA6HlS53PcZhLdM= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-117-ccZ_NuuzPJmNFgfbXgF-7w-1; Thu, 24 Oct 2024 23:35:10 -0400 X-MC-Unique: ccZ_NuuzPJmNFgfbXgF-7w-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 961871955D47 for ; Fri, 25 Oct 2024 03:35:09 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A30DD300018D; Fri, 25 Oct 2024 03:35:08 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 08/11] New test - gdb.base/tls-nothreads.exp Date: Thu, 24 Oct 2024 19:26:26 -0700 Message-ID: <20241025033431.36274-9-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 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, KAM_SHORT, 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 introduces a new test, gdb.base/tls-nothreads.exp. It has a test case, a C file, which has several TLS variables in the main program, which, once compiled and linked, should end up (in ELF files) in .tdata and .tbss. The test compiles the program in a number of different ways, making sure that each variable is accessible regardless of how it was compiled. Note that some of the compilation scenarios end up with a statically linked executable. Prior to this series of commits, accessing TLS variables from a statically linked program on Linux did not work. For certain targets (x86_64, aarch64, s390x, riscv, and ppc64), all on Linux, support has been added to GDB for accessing thread local storage in statically linked executables. This test is important for testing those build scenarios. But it's also important to make sure that GDB's internal TLS support works for other scenarios too. In order to accomplish that, the tests are also run in a mode which forces the internal support to be used. It also adds a new file, gdb.base/tls-common.exp.tcl, which includes some common definitions used by the three new TLS tests, including the one added by this commit. In particular, it sets a TCL variable, 'internal_tls_linux_targets' which list the targets mentioned earlier. This means that as internal TLS support is added for other targets, the target should be listed in just one file as opposed to three (or more if other tests using tls-common.exp.tcl are added). --- gdb/testsuite/gdb.base/tls-common.exp.tcl | 50 +++++ gdb/testsuite/gdb.base/tls-nothreads.c | 57 +++++ gdb/testsuite/gdb.base/tls-nothreads.exp | 248 ++++++++++++++++++++++ 3 files changed, 355 insertions(+) create mode 100644 gdb/testsuite/gdb.base/tls-common.exp.tcl create mode 100644 gdb/testsuite/gdb.base/tls-nothreads.c create mode 100644 gdb/testsuite/gdb.base/tls-nothreads.exp diff --git a/gdb/testsuite/gdb.base/tls-common.exp.tcl b/gdb/testsuite/gdb.base/tls-common.exp.tcl new file mode 100644 index 00000000000..7aa7f466aa1 --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-common.exp.tcl @@ -0,0 +1,50 @@ +# Copyright 2024 Free Software Foundation, Inc. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# Require statement, variables and procs used by tls-nothreads.exp, +# tls-multiobj.exp, and tls-dlobj.exp. + +# The tests listed above are known to work for the targets listed on +# the 'require' line, below. +# +# At the moment, only the Linux target is listed, but, ideally, these +# tests should be run on other targets too. E.g, testing on FreeBSD +# shows many failures which should be addressed in some fashion before +# enabling it for that target. + +require {is_any_target "*-*-linux*"} + +# These are the targets which have support for internal TLS lookup: + +set internal_tls_linux_targets {"x86_64-*-linux*" "aarch64-*-linux*" + "riscv*-*-linux*" "powerpc64*-*-linux*" + "s390x*-*-linux*"} + +# The "maint set force-internal-tls-address-lookup" command is only +# available for certain Linux architectures. Don't attempt to force +# use of internal TLS support for architectures which don't support +# it. + +if [is_any_target {*}$internal_tls_linux_targets] { + set internal_tls_iters { false true } +} else { + set internal_tls_iters { false } +} + +# Set up a kfail with message KFAIL_MSG when KFAIL_COND holds, then +# issue gdb_test with command CMD and regular expression RE. + +proc gdb_test_with_kfail {cmd re kfail_cond kfail_msg} { + if [uplevel 1 [list expr $kfail_cond]] { + setup_kfail $kfail_msg *-*-* + } + gdb_test $cmd $re +} diff --git a/gdb/testsuite/gdb.base/tls-nothreads.c b/gdb/testsuite/gdb.base/tls-nothreads.c new file mode 100644 index 00000000000..b3aaa3383e7 --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-nothreads.c @@ -0,0 +1,57 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +__thread int tls_tbss_1; +__thread int tls_tbss_2; +__thread int tls_tbss_3; + +__thread int tls_tdata_1 = 21; +__thread int tls_tdata_2 = 22; +__thread int tls_tdata_3 = 23; + +volatile int data; + +void +use_it (int a) +{ + data = a; +} + +int +main (int argc, char **argv) +{ + use_it (-1); + + tls_tbss_1 = 24; /* main-breakpoint-1 */ + tls_tbss_2 = 25; + tls_tbss_3 = 26; + + tls_tdata_1 = 42; + tls_tdata_2 = 43; + tls_tdata_3 = 44; + + use_it (tls_tbss_1); + use_it (tls_tbss_2); + use_it (tls_tbss_3); + use_it (tls_tdata_1); + use_it (tls_tdata_2); + use_it (tls_tdata_3); + + use_it (100); /* main-breakpoint-2 */ + + return 0; +} diff --git a/gdb/testsuite/gdb.base/tls-nothreads.exp b/gdb/testsuite/gdb.base/tls-nothreads.exp new file mode 100644 index 00000000000..d235d1a2ab5 --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-nothreads.exp @@ -0,0 +1,248 @@ +# Copyright 2024 Free Software Foundation, Inc. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# Using different compilation/linking scenarios, attempt to access +# thread-local variables in a non-threaded program. Also test that +# GDB internal TLS lookup works correctly. + +source $srcdir/$subdir/tls-common.exp.tcl + +standard_testfile + +proc do_tests {force_internal_tls {do_kfail_tls_access 0}} { + clean_restart $::binfile + if ![runto_main] { + return + } + + if $force_internal_tls { + gdb_test_no_output "maint set force-internal-tls-address-lookup on" + } + + if { $do_kfail_tls_access && [istarget "*-*-linux*"] } { + # Turn off do_kfail_tls_access when libthread_db is loaded. + # This can happen for the default case when testing x86_64 + # w/ -m32 using glibc versions 2.34 or newer. + gdb_test_multiple "maint check libthread-db" "Check for loaded libthread_db" { + -re -wrap "libthread_db integrity checks passed." { + set do_kfail_tls_access 0 + pass $gdb_test_name + } + -re -wrap "No libthread_db loaded" { + pass $gdb_test_name + } + } + # Also turn off do_kfail_tls_access when connected to a + # gdbserver and we observe that accessing a TLS variable + # works. + if [target_is_gdbserver] { + gdb_test_multiple "print tls_tbss_1" "Check TLS accessibility when connected to a gdbserver" { + -re -wrap "= 0" { + set do_kfail_tls_access 0 + pass $gdb_test_name + } + -re -wrap "Remote target failed to process qGetTLSAddr request" { + pass $gdb_test_name + } + } + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"] + gdb_continue_to_breakpoint "main-breakpoint-1" + + set t $do_kfail_tls_access + set m "tls not available" + with_test_prefix "before assignments" { + gdb_test_with_kfail "print tls_tbss_1" ".* = 0" $t $m + gdb_test_with_kfail "print tls_tbss_2" ".* = 0" $t $m + gdb_test_with_kfail "print tls_tbss_3" ".* = 0" $t $m + + gdb_test_with_kfail "print tls_tdata_1" ".* = 21" $t $m + gdb_test_with_kfail "print tls_tdata_2" ".* = 22" $t $m + gdb_test_with_kfail "print tls_tdata_3" ".* = 23" $t $m + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"] + gdb_continue_to_breakpoint "main-breakpoint-2" + + with_test_prefix "after assignments" { + gdb_test_with_kfail "print tls_tbss_1" ".* = 24" $t $m + gdb_test_with_kfail "print tls_tbss_2" ".* = 25" $t $m + gdb_test_with_kfail "print tls_tbss_3" ".* = 26" $t $m + + gdb_test_with_kfail "print tls_tdata_1" ".* = 42" $t $m + gdb_test_with_kfail "print tls_tdata_2" ".* = 43" $t $m + gdb_test_with_kfail "print tls_tdata_3" ".* = 44" $t $m + } + + # Make a core file now, but save testing using it until the end + # in case core files are not supported. + set corefile ${::binfile}.core + set core_supported 0 + if { ![is_remote host] } { + set core_supported [gdb_gcore_cmd $corefile "save corefile"] + } + + # Now continue to end and see what happens when attempting to + # access a TLS variable when the program is no longer running. + gdb_continue_to_end + with_test_prefix "after exit" { + gdb_test "print tls_tbss_1" \ + "Cannot read `tls_tbss_1' without registers" + } + + with_test_prefix "stripped" { + set binfile_stripped "${::binfile}.stripped" + set objcopy [gdb_find_objcopy] + set cmd "$objcopy --strip-debug ${::binfile} $binfile_stripped" + if ![catch "exec $cmd" cmd_output] { + clean_restart $binfile_stripped + if ![runto_main] { + return + } + + if $force_internal_tls { + gdb_test_no_output "maint set force-internal-tls-address-lookup on" + } + + # While there are no debug (e.g. DWARF) symbols, there + # are minimal symbols, so we should be able to place a + # breakpoint in use_it and continue to it. Continuing + # twice should put us past the assignments, at which point + # we can see if the TLS variables are still accessible. + gdb_test "break use_it" "Breakpoint 2 at $::hex" + gdb_test "continue" "Breakpoint 2, $::hex in use_it.*" + gdb_test "continue" "Breakpoint 2, $::hex in use_it.*" "continue 2" + + # Note that a cast has been added in order to avoid the + # "...has unknown type; cast it to its declared type" + # problem. + gdb_test_with_kfail "print (int) tls_tbss_1" ".* = 24" $t $m + gdb_test_with_kfail "print (int) tls_tbss_2" ".* = 25" $t $m + gdb_test_with_kfail "print (int) tls_tbss_3" ".* = 26" $t $m + + gdb_test_with_kfail "print (int) tls_tdata_1" ".* = 42" $t $m + gdb_test_with_kfail "print (int) tls_tdata_2" ".* = 43" $t $m + gdb_test_with_kfail "print (int) tls_tdata_3" ".* = 44" $t $m + + # Get rid of the "use_it" breakpoint + gdb_test_no_output "del 2" + + # Continue to program exit + gdb_continue_to_end + + # TLS variables should not be accessible after program exit + # (This case initially caused GDB to crash during development + # of GDB-internal TLS lookup support.) + with_test_prefix "after exit" { + gdb_test "print (int) tls_tbss_1" \ + "Cannot determine address of TLS symbol `tls_tbss_1' without registers" + } + } + } + + # Finish test early if no core file was made. + if !$core_supported { + return + } + + clean_restart $::binfile + + set core_loaded [gdb_core_cmd $corefile "load corefile"] + if { $core_loaded == -1 } { + return + } + + with_test_prefix "core file" { + if $force_internal_tls { + gdb_test_no_output "maint set force-internal-tls-address-lookup on" + } + + gdb_test_with_kfail "print tls_tbss_1" ".* = 24" $t $m + gdb_test_with_kfail "print tls_tbss_2" ".* = 25" $t $m + gdb_test_with_kfail "print tls_tbss_3" ".* = 26" $t $m + + gdb_test_with_kfail "print tls_tdata_1" ".* = 42" $t $m + gdb_test_with_kfail "print tls_tdata_2" ".* = 43" $t $m + gdb_test_with_kfail "print tls_tdata_3" ".* = 44" $t $m + } +} + +# Certain linux target architectures implement support for internal +# TLS lookup which is used when thread stratum support (via +# libthread_db) is missing or when the linux-only GDB maintenance +# setting 'force-internal-tls-address-lookup' is 'on'. Thus for some +# of the testing scenarios, such as statically linked executables, +# this internal support will be used. Set 'do_kfail_tls_access' to 1 +# for those architectures which don't implement internal TLS support. +if {[istarget *-*-linux*] + && ![is_any_target {*}$internal_tls_linux_targets]} { + set do_kfail_tls_access 1 +} elseif {[istarget *-*-linux*] && [is_x86_like_target]} { + # This covers the case of x86_64 with -m32: + set do_kfail_tls_access 1 +} else { + set do_kfail_tls_access 0 +} + +set binprefix $binfile + +with_test_prefix "default" { + set binfile $binprefix-default + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "failed to compile" + } else { + foreach_with_prefix force_internal_tls $internal_tls_iters { + # Depending on glibc version, it might not be appropriate + # for do_kfail_tls_access to be set here. That will be + # handled in 'do_tests', disabling it if necessary. + # + # Specifically, glibc versions 2.34 and later have the + # thread library (and libthread_db availability) in + # programs not linked against libpthread.so + do_tests $force_internal_tls $do_kfail_tls_access + } + } +} + +with_test_prefix "static" { + set binfile $binprefix-static + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug "additional_flags=-static"}] != "" } { + untested "failed to compile" + } else { + foreach_with_prefix force_internal_tls $internal_tls_iters { + do_tests $force_internal_tls $do_kfail_tls_access + } + } +} + +with_test_prefix "pthreads" { + set binfile $binprefix-pthreads + if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "failed to compile" + } else { + foreach_with_prefix force_internal_tls $internal_tls_iters { + do_tests $force_internal_tls + } + } +} + +with_test_prefix "pthreads-static" { + set binfile $binprefix-pthreads-static + if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug "additional_flags=-static"}] != "" } { + untested "failed to compile" + } else { + foreach_with_prefix force_internal_tls $internal_tls_iters { + do_tests $force_internal_tls $do_kfail_tls_access + } + } +} From patchwork Fri Oct 25 02:26:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99525 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 B1C4E385842A for ; Fri, 25 Oct 2024 03:38:41 +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 2FFCA3858C2B for ; Fri, 25 Oct 2024 03:35:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2FFCA3858C2B 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 2FFCA3858C2B 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=1729827325; cv=none; b=dpk6GFWUCuU5o61s3lCI4y5AlFw6Da5vq59hu9tq6Iq95XJupRU6joWYtlSD037U1MGTo4Hm6zjaOG4DAmefqw3FbDkvf+j5WxGkO2GedRwYRw1n7DnivJKB3dCGECu2pcvX6vcnbq4T1xVVKixugEuIOSsI4ue5OiTpWPHp9Fg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827325; c=relaxed/simple; bh=lExHqXI6PleUlAF8H9jn7TQ/nR/3ZW5DfZRJTCwDBhA=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=w1jQUxjm/hh9xIcA4Es0tMm1sXEZitMf2BhJuoW4ap8JUSTrfsXA15bfUBpLwRNj10tzyuz0pjZV7G0JPBrOXEKXa9vjzIbJoZvmp3HrFw4tBABQFOMvDcVshmlQQJGw4ZmdAVhSDROV51aXx2lUvpKRpWViHn/aVobDgp0dtVQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827312; 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=1dHwJXAnTkVaBfChhEJ0plQNCnaXNuJozw4E4m5w4Ik=; b=WH70AmNDBKvI6xRfaQom0Hgwu4yH5Ggh4FhV6ffUJGL7/aUZHrqxQsxPUzEYm2AJhv4Eip NARG5yNbOnP+uHP3cjrVR9vpdJbLugH1ytNq273UK0oAXimqzRYukOR3oCKd4aMErI1jpz LlaL3OPhadYn1UA2W6gjdHSBlgFG1g0= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-342-tg8vWn_7OtKJO1J30VgPSA-1; Thu, 24 Oct 2024 23:35:11 -0400 X-MC-Unique: tg8vWn_7OtKJO1J30VgPSA-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AFB311955DCD for ; Fri, 25 Oct 2024 03:35:10 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D8AEB300018D; Fri, 25 Oct 2024 03:35:09 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 09/11] New test - gdb.base/tls-multiobj.exp Date: Thu, 24 Oct 2024 19:26:27 -0700 Message-ID: <20241025033431.36274-10-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, 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 test exercises GDB's internal TLS support when both the main program and several shared libraries have TLS variables. It also tests existing (non-internal) TLS support too. It tests using two compilation scenarios, "default", in which libpthread is not linked with the program and libraries as well as one which does use libpthread. It tests link map address to module id mapping code in GDB in addition to the ability of GDB to traverse TLS data structures with several libraries in play. --- gdb/testsuite/gdb.base/tls-multiobj.c | 89 +++++++++ gdb/testsuite/gdb.base/tls-multiobj.exp | 230 ++++++++++++++++++++++++ gdb/testsuite/gdb.base/tls-multiobj1.c | 26 +++ gdb/testsuite/gdb.base/tls-multiobj2.c | 26 +++ gdb/testsuite/gdb.base/tls-multiobj3.c | 26 +++ 5 files changed, 397 insertions(+) create mode 100644 gdb/testsuite/gdb.base/tls-multiobj.c create mode 100644 gdb/testsuite/gdb.base/tls-multiobj.exp create mode 100644 gdb/testsuite/gdb.base/tls-multiobj1.c create mode 100644 gdb/testsuite/gdb.base/tls-multiobj2.c create mode 100644 gdb/testsuite/gdb.base/tls-multiobj3.c diff --git a/gdb/testsuite/gdb.base/tls-multiobj.c b/gdb/testsuite/gdb.base/tls-multiobj.c new file mode 100644 index 00000000000..10e67da54d8 --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-multiobj.c @@ -0,0 +1,89 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +__thread int tls_main_tbss_1; +__thread int tls_main_tbss_2; +__thread int tls_main_tdata_1 = 96; +__thread int tls_main_tdata_2 = 97; + +extern __thread int tls_lib1_tbss_1; +extern __thread int tls_lib1_tbss_2; +extern __thread int tls_lib1_tdata_1; +extern __thread int tls_lib1_tdata_2; + +extern __thread int tls_lib2_tbss_1; +extern __thread int tls_lib2_tbss_2; +extern __thread int tls_lib2_tdata_1; +extern __thread int tls_lib2_tdata_2; + +extern __thread int tls_lib3_tbss_1; +extern __thread int tls_lib3_tbss_2; +extern __thread int tls_lib3_tdata_1; +extern __thread int tls_lib3_tdata_2; + +extern void lib1_func (); +extern void lib2_func (); +extern void lib3_func (); + +volatile int data; + +void +use_it (int a) +{ + data = a; +} + +int +main (int argc, char **argv) +{ + use_it (-1); + + tls_main_tbss_1 = 51; /* main-breakpoint-1 */ + tls_main_tbss_2 = 52; + tls_main_tdata_1 = 53; + tls_main_tdata_2 = 54; + + tls_lib1_tbss_1 = 151; + tls_lib1_tbss_2 = 152; + tls_lib1_tdata_1 = 153; + tls_lib1_tdata_2 = 154; + + tls_lib2_tbss_1 = 251; + tls_lib2_tbss_2 = 252; + tls_lib2_tdata_1 = 253; + tls_lib2_tdata_2 = 254; + + tls_lib3_tbss_1 = 351; + tls_lib3_tbss_2 = 352; + tls_lib3_tdata_1 = 353; + tls_lib3_tdata_2 = 354; + + lib1_func (); + lib2_func (); + lib3_func (); + + /* Attempt to keep variables in the main program from being optimized + away. */ + use_it (tls_main_tbss_1); + use_it (tls_main_tbss_2); + use_it (tls_main_tdata_1); + use_it (tls_main_tdata_2); + + use_it (100); /* main-breakpoint-2 */ + + return 0; +} diff --git a/gdb/testsuite/gdb.base/tls-multiobj.exp b/gdb/testsuite/gdb.base/tls-multiobj.exp new file mode 100644 index 00000000000..a78db1460e9 --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-multiobj.exp @@ -0,0 +1,230 @@ +# Copyright 2024 Free Software Foundation, Inc. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# Using different compilation/linking scenarios, attempt to access +# thread-local variables in a non-threaded program using multiple +# shared objects. + +source $srcdir/$subdir/tls-common.exp.tcl + +standard_testfile + +set lib1src "${srcdir}/${subdir}/${testfile}1.c" +set lib2src "${srcdir}/${subdir}/${testfile}2.c" +set lib3src "${srcdir}/${subdir}/${testfile}3.c" + +set lib1obj [standard_output_file "${testfile}1-lib.so"] +set lib2obj [standard_output_file "${testfile}2-lib.so"] +set lib3obj [standard_output_file "${testfile}3-lib.so"] + +proc do_tests {force_internal_tls {do_kfail_tls_access 0}} { + clean_restart $::binfile + if ![runto_main] { + return + } + + if $force_internal_tls { + gdb_test_no_output "maint set force-internal-tls-address-lookup on" + } + + if { $do_kfail_tls_access && [istarget "*-*-linux*"] } { + # Turn off do_kfail_tls_access when libthread_db is loaded. + # This can happen for the default case when testing x86_64 + # w/ -m32 using glibc versions 2.34 or newer. + gdb_test_multiple "maint check libthread-db" "Check for loaded libthread_db" { + -re -wrap "libthread_db integrity checks passed." { + set do_kfail_tls_access 0 + pass $gdb_test_name + } + -re -wrap "No libthread_db loaded" { + pass $gdb_test_name + } + } + # Also turn off do_kfail_tls_access when connected to a + # gdbserver and we observe that accessing a TLS variable + # works. + if [target_is_gdbserver] { + gdb_test_multiple "print tls_main_tbss_1" \ + "Check TLS accessibility when connected to a gdbserver" { + -re -wrap "= 0" { + set do_kfail_tls_access 0 + pass $gdb_test_name + } + -re -wrap "Remote target failed to process qGetTLSAddr request" { + pass $gdb_test_name + } + } + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"] + gdb_continue_to_breakpoint "main-breakpoint-1" + + set t $do_kfail_tls_access + set m "tls not available" + with_test_prefix "before assignments" { + gdb_test_with_kfail "print tls_main_tbss_1" ".* = 0" $t $m + gdb_test_with_kfail "print tls_main_tbss_2" ".* = 0" $t $m + gdb_test_with_kfail "print tls_main_tdata_1" ".* = 96" $t $m + gdb_test_with_kfail "print tls_main_tdata_2" ".* = 97" $t $m + + gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 0" $t $m + gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 0" $t $m + gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 196" $t $m + gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 197" $t $m + + gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 0" $t $m + gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 0" $t $m + gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 296" $t $m + gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 297" $t $m + + gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 0" $t $m + gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 0" $t $m + gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 396" $t $m + gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 397" $t $m + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"] + gdb_continue_to_breakpoint "main-breakpoint-2" + + with_test_prefix "after assignments" { + gdb_test_with_kfail "print tls_main_tbss_1" ".* = 51" $t $m + gdb_test_with_kfail "print tls_main_tbss_2" ".* = 52" $t $m + gdb_test_with_kfail "print tls_main_tdata_1" ".* = 53" $t $m + gdb_test_with_kfail "print tls_main_tdata_2" ".* = 54" $t $m + + gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 151" $t $m + gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 152" $t $m + gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 153" $t $m + gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 154" $t $m + + gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 251" $t $m + gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 252" $t $m + gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 253" $t $m + gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 254" $t $m + + gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 351" $t $m + gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 352" $t $m + gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 353" $t $m + gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 354" $t $m + } + + set corefile ${::binfile}.core + set core_supported 0 + if { ![is_remote host] } { + set core_supported [gdb_gcore_cmd $corefile "save corefile"] + } + + # Finish test early if no core file was made. + if !$core_supported { + return + } + + clean_restart $::binfile + + set core_loaded [gdb_core_cmd $corefile "load corefile"] + if { $core_loaded == -1 } { + return + } + + with_test_prefix "core file" { + if $force_internal_tls { + gdb_test_no_output "maint set force-internal-tls-address-lookup on" + } + + gdb_test_with_kfail "print tls_main_tbss_1" ".* = 51" $t $m + gdb_test_with_kfail "print tls_main_tbss_2" ".* = 52" $t $m + gdb_test_with_kfail "print tls_main_tdata_1" ".* = 53" $t $m + gdb_test_with_kfail "print tls_main_tdata_2" ".* = 54" $t $m + + gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 151" $t $m + gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 152" $t $m + gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 153" $t $m + gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 154" $t $m + + gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 251" $t $m + gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 252" $t $m + gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 253" $t $m + gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 254" $t $m + + gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 351" $t $m + gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 352" $t $m + gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 353" $t $m + gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 354" $t $m + } +} + +if { [gdb_compile_shlib $lib1src $lib1obj {debug}] != "" } { + untested "failed to compile shared object" + return -1 +} +if { [gdb_compile_shlib $lib2src $lib2obj {debug}] != "" } { + untested "failed to compile shared object" + return -1 +} +if { [gdb_compile_shlib $lib3src $lib3obj {debug}] != "" } { + untested "failed to compile shared object" + return -1 +} + +# Certain linux target architectures implement support for internal +# TLS lookup which is used when thread stratum support (via +# libthread_db) is missing or when the linux-only GDB maintenance +# setting 'force-internal-tls-address-lookup' is 'on'. Thus for some +# of the testing scenarios, such as statically linked executables, +# this internal support will be used. Set 'do_kfail_tls_access' to 1 +# for those architectures which don't implement internal tls support. +if {[istarget *-*-linux*] + && ![is_any_target {*}$internal_tls_linux_targets]} { + set do_kfail_tls_access 1 +} elseif {[istarget *-*-linux*] && [is_x86_like_target]} { + # This covers the case of x86_64 with -m32: + set do_kfail_tls_access 1 +} else { + set do_kfail_tls_access 0 +} + +set binprefix $binfile + +with_test_prefix "default" { + set binfile $binprefix-default + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \ + [list debug shlib=${lib1obj} \ + shlib=${lib2obj} \ + shlib=${lib3obj}]] != "" } { + untested "failed to compile" + } else { + foreach_with_prefix force_internal_tls $internal_tls_iters { + # Depending on glibc version, it might not be appropriate + # for do_kfail_tls_access to be set here. That will be + # handled in 'do_tests', disabling it if necessary. + # + # Specifically, glibc versions 2.34 and later have the + # thread library (and libthread_db availability) in + # programs not linked against libpthread.so + do_tests $force_internal_tls $do_kfail_tls_access + } + } +} + +with_test_prefix "pthreads" { + set binfile $binprefix-pthreads + if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \ + [list debug shlib=${lib1obj} \ + shlib=${lib2obj} \ + shlib=${lib3obj}]] != "" } { + untested "failed to compile" + } else { + foreach_with_prefix force_internal_tls $internal_tls_iters { + do_tests $force_internal_tls + } + } +} diff --git a/gdb/testsuite/gdb.base/tls-multiobj1.c b/gdb/testsuite/gdb.base/tls-multiobj1.c new file mode 100644 index 00000000000..86e72228b1b --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-multiobj1.c @@ -0,0 +1,26 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +__thread int tls_lib1_tbss_1; +__thread int tls_lib1_tbss_2; +__thread int tls_lib1_tdata_1 = 196; +__thread int tls_lib1_tdata_2 = 197; + +void +lib1_func () +{ +} diff --git a/gdb/testsuite/gdb.base/tls-multiobj2.c b/gdb/testsuite/gdb.base/tls-multiobj2.c new file mode 100644 index 00000000000..cea07092a5d --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-multiobj2.c @@ -0,0 +1,26 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +__thread int tls_lib2_tbss_1; +__thread int tls_lib2_tbss_2; +__thread int tls_lib2_tdata_1 = 296; +__thread int tls_lib2_tdata_2 = 297; + +void +lib2_func () +{ +} diff --git a/gdb/testsuite/gdb.base/tls-multiobj3.c b/gdb/testsuite/gdb.base/tls-multiobj3.c new file mode 100644 index 00000000000..bb0f2395fbf --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-multiobj3.c @@ -0,0 +1,26 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +__thread int tls_lib3_tbss_1; +__thread int tls_lib3_tbss_2; +__thread int tls_lib3_tdata_1 = 396; +__thread int tls_lib3_tdata_2 = 397; + +void +lib3_func () +{ +} From patchwork Fri Oct 25 02:26:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99526 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 A9A1E385843B for ; Fri, 25 Oct 2024 03:38:57 +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 9D5A43858CD9 for ; Fri, 25 Oct 2024 03:35:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9D5A43858CD9 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 9D5A43858CD9 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=1729827325; cv=none; b=Kn7It8nElfaAvwjjetWBSj7eN3YzzzmgXT8QH4RNMEOH4PNiwb+z/8FENH86sqemjzsQ2Rm1TwPbvw3tEAHONCbHpOp+8cM6U6dHeCyHwuVmQaquZDn2LvYwqpusekwqAEocnfw9ufqSH5n6uQCp4nQcYHmXX54j3a3lQFbS2WQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827325; c=relaxed/simple; bh=8Y3zDRkf/Fuia4MXLtyM5i7EPGLcpRSH+EOxaBml6/s=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=gkroYarHZCvECz/rPDT4M4vm5E2bf8x5M42fck5//RtkWJ0gL20GgxTR/LuCp2SDy/e+8WlJEeEIfBKVr/AXdZXEW0j6oGw/W12S8v6Jrxm9DMFhGjHNgCecUJv3vQSRKBnIlB4eQ3NEYtlHhgoKe2ZGsjYxFigPpx2ObwwLxTU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827314; 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=vXLSOPLrr7NinWifzFhRqgiU/BLBtIaGdLx0UqECB+8=; b=CTEZKwnQ22dsbKpeXzawYk10ijEhDU4xPnrqXmm57Mjo3hTPWv/4Dn7ddLhr7dRKrupYFT GJCBC6Qd85X8B7WR8QFr39s4qsgGAtLsN2GDqdxc4q2NDrZExxWCDRqICVsVMKQYMxoB7h vrq0Dk3rpJyiw9Svzn70K41AR4CBATU= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-519-2X34DNuMOD6t5TuzIlABDA-1; Thu, 24 Oct 2024 23:35:12 -0400 X-MC-Unique: 2X34DNuMOD6t5TuzIlABDA-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EF6F919560AE for ; Fri, 25 Oct 2024 03:35:11 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1AC7A300018D; Fri, 25 Oct 2024 03:35:10 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 10/11] New test - gdb.base/tls-dlobj.exp Date: Thu, 24 Oct 2024 19:26:28 -0700 Message-ID: <20241025033431.36274-11-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 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, KAM_SHORT, 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 test exercises musl_link_map_to_tls_module_id() and glibc_link_map_to_tls_module_id(), both of which are in solib-svr4.c. Prior to writing this test, I had only written what is now named 'musl_link_map_to_tls_module_id' and it worked for both GLIBC and MUSL. Once I wrote this new test, tls-dlobj.exp, there were a number of tests which didn't work with GLIBC. This led me to write a GLIBC-specific link map to module id function, i.e, 'glibc_link_map_to_tls_module_id'. It only has one compilation scenario, in which the pthread(s) library is used - as noted in a comment, it became too much of a hassle to try to KFAIL things, though it certainly could have been done in much the same was as was done in gdb.base/multiobj.exp. It didn't seem that important to do so, however, since I believe that the other tests have adequate coverage for different compilation scenarios. --- gdb/testsuite/gdb.base/tls-dlobj-lib.c | 87 ++++++ gdb/testsuite/gdb.base/tls-dlobj.c | 311 ++++++++++++++++++++ gdb/testsuite/gdb.base/tls-dlobj.exp | 378 +++++++++++++++++++++++++ 3 files changed, 776 insertions(+) create mode 100644 gdb/testsuite/gdb.base/tls-dlobj-lib.c create mode 100644 gdb/testsuite/gdb.base/tls-dlobj.c create mode 100644 gdb/testsuite/gdb.base/tls-dlobj.exp diff --git a/gdb/testsuite/gdb.base/tls-dlobj-lib.c b/gdb/testsuite/gdb.base/tls-dlobj-lib.c new file mode 100644 index 00000000000..3f8ebc4f6a7 --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-dlobj-lib.c @@ -0,0 +1,87 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* This program needs to be compiled with preprocessor symbol set to + a small integer, e.g. "gcc -DN=1 ..." With N defined, the CONCAT2 + and CONCAT3 macros will construct suitable names for the global + variables and functions. */ + +#define CONCAT2(a,b) CONCAT2_(a,b) +#define CONCAT2_(a,b) a ## b + +#define CONCAT3(a,b,c) CONCAT3_(a,b,c) +#define CONCAT3_(a,b,c) a ## b ## c + +/* For N=1, this ends up being... + __thread int tls_lib1_tbss_1; + __thread int tls_lib1_tbss_2; + __thread int tls_lib1_tdata_1 = 196; + __thread int tls_lib1_tdata_2 = 197; */ + +__thread int CONCAT3(tls_lib, N, _tbss_1); +__thread int CONCAT3(tls_lib, N, _tbss_2); +__thread int CONCAT3(tls_lib, N, _tdata_1) = CONCAT2(N, 96); +__thread int CONCAT3(tls_lib, N, _tdata_2) = CONCAT2(N, 97); + +/* Substituting for N, define function: + + int get_tls_libN_var (int which) . */ + +int +CONCAT3(get_tls_lib, N, _var) (int which) +{ + switch (which) + { + case 0: + return -1; + case 1: + return CONCAT3(tls_lib, N, _tbss_1); + case 2: + return CONCAT3(tls_lib, N, _tbss_2); + case 3: + return CONCAT3(tls_lib, N, _tdata_1); + case 4: + return CONCAT3(tls_lib, N, _tdata_2); + } + return -1; +} + +/* Substituting for N, define function: + + void set_tls_libN_var (int which, int val) . */ + +void +CONCAT3(set_tls_lib, N, _var) (int which, int val) +{ + switch (which) + { + case 0: + break; + case 1: + CONCAT3(tls_lib, N, _tbss_1) = val; + break; + case 2: + CONCAT3(tls_lib, N, _tbss_2) = val; + break; + case 3: + CONCAT3(tls_lib, N, _tdata_1) = val; + break; + case 4: + CONCAT3(tls_lib, N, _tdata_2) = val; + break; + } +} diff --git a/gdb/testsuite/gdb.base/tls-dlobj.c b/gdb/testsuite/gdb.base/tls-dlobj.c new file mode 100644 index 00000000000..322bdda0393 --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-dlobj.c @@ -0,0 +1,311 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2024 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include +#include +#include + +typedef void (*setter_ftype) (int which, int val); + +__thread int tls_main_tbss_1; +__thread int tls_main_tbss_2; +__thread int tls_main_tdata_1 = 96; +__thread int tls_main_tdata_2 = 97; + +extern void set_tls_lib10_var (int which, int val); +extern void set_tls_lib11_var (int which, int val); + +volatile int data; + +static void +set_tls_main_var (int which, int val) +{ + switch (which) + { + case 1: + tls_main_tbss_1 = val; + break; + case 2: + tls_main_tbss_2 = val; + break; + case 3: + tls_main_tdata_1 = val; + break; + case 4: + tls_main_tdata_2 = val; + break; + } +} + +void +use_it (int a) +{ + data = a; +} + +static void * +load_dso (char *dso_name, int n, setter_ftype *setterp) +{ + char buf[80]; + void *sym; + void *handle = dlopen (dso_name, RTLD_NOW | RTLD_GLOBAL); + if (handle == NULL) + { + fprintf (stderr, "dlopen of DSO '%s' failed: %s\n", dso_name, dlerror ()); + exit (1); + } + sprintf (buf, "set_tls_lib%d_var", n); + sym = dlsym (handle, buf); + assert (sym != NULL); + *setterp = sym; + + /* Some libc implementations (for some architectures) refuse to + initialize TLS data structures (specifically, the DTV) without + first calling dlsym on one of the TLS symbols. */ + sprintf (buf, "tls_lib%d_tdata_1", n); + assert (dlsym (handle, buf) != NULL); + + return handle; +} + +int +main (int argc, char **argv) +{ + int i, status; + setter_ftype s0, s1, s2, s3, s4, s10, s11; + void *h1 = load_dso (OBJ1, 1, &s1); + void *h2 = load_dso (OBJ2, 2, &s2); + void *h3 = load_dso (OBJ3, 3, &s3); + void *h4 = load_dso (OBJ4, 4, &s4); + s0 = set_tls_main_var; + s10 = set_tls_lib10_var; + s11 = set_tls_lib11_var; + + use_it (0); /* main-breakpoint-1 */ + + /* Set TLS variables in main program and all libraries. */ + for (i = 1; i <= 4; i++) + s0 (i, 10 + i); + for (i = 1; i <= 4; i++) + s1 (i, 110 + i); + for (i = 1; i <= 4; i++) + s2 (i, 210 + i); + for (i = 1; i <= 4; i++) + s3 (i, 310 + i); + for (i = 1; i <= 4; i++) + s4 (i, 410 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1010 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1110 + i); + + use_it (0); /* main-breakpoint-2 */ + + /* Unload lib2 and lib3. */ + status = dlclose (h2); + assert (status == 0); + status = dlclose (h3); + assert (status == 0); + + /* Set TLS variables in main program and in libraries which are still + loaded. */ + for (i = 1; i <= 4; i++) + s0 (i, 20 + i); + for (i = 1; i <= 4; i++) + s1 (i, 120 + i); + for (i = 1; i <= 4; i++) + s4 (i, 420 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1020 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1120 + i); + + use_it (0); /* main-breakpoint-3 */ + + /* Load lib3. */ + h3 = load_dso (OBJ3, 3, &s3); + + /* Set TLS vars again; currently, only lib2 is not loaded. */ + for (i = 1; i <= 4; i++) + s0 (i, 30 + i); + for (i = 1; i <= 4; i++) + s1 (i, 130 + i); + for (i = 1; i <= 4; i++) + s3 (i, 330 + i); + for (i = 1; i <= 4; i++) + s4 (i, 430 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1030 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1130 + i); + + use_it (0); /* main-breakpoint-4 */ + + /* Unload lib1 and lib4; load lib2. */ + status = dlclose (h1); + assert (status == 0); + status = dlclose (h4); + assert (status == 0); + h2 = load_dso (OBJ2, 2, &s2); + + /* Set TLS vars; currently, lib2 and lib3 are loaded, + lib1 and lib4 are not. */ + for (i = 1; i <= 4; i++) + s0 (i, 40 + i); + for (i = 1; i <= 4; i++) + s2 (i, 240 + i); + for (i = 1; i <= 4; i++) + s3 (i, 340 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1040 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1140 + i); + + use_it (0); /* main-breakpoint-5 */ + + /* Load lib4 and lib1. Unload lib2. */ + h4 = load_dso (OBJ4, 4, &s4); + h1 = load_dso (OBJ1, 1, &s1); + status = dlclose (h2); + assert (status == 0); + + /* Set TLS vars; currently, lib1, lib3, and lib4 are loaded; + lib2 is not loaded. */ + for (i = 1; i <= 4; i++) + s0 (i, 50 + i); + for (i = 1; i <= 4; i++) + s1 (i, 150 + i); + for (i = 1; i <= 4; i++) + s3 (i, 350 + i); + for (i = 1; i <= 4; i++) + s4 (i, 450 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1050 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1150 + i); + + use_it (0); /* main-breakpoint-6 */ + + /* Load lib2, unload lib1, lib3, and lib4; then load lib3 again. */ + h2 = load_dso (OBJ2, 2, &s2); + status = dlclose (h1); + assert (status == 0); + status = dlclose (h3); + assert (status == 0); + status = dlclose (h4); + assert (status == 0); + h3 = load_dso (OBJ3, 3, &s3); + + /* Set TLS vars; currently, lib2 and lib3 are loaded; + lib1 and lib4 are not loaded. */ + for (i = 1; i <= 4; i++) + s0 (i, 60 + i); + for (i = 1; i <= 4; i++) + s2 (i, 260 + i); + for (i = 1; i <= 4; i++) + s3 (i, 360 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1060 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1160 + i); + + use_it (0); /* main-breakpoint-7 */ + + /* Unload lib3 and lib2, then (re)load lib4, lib3, lib2, and lib1, + in that order. */ + status = dlclose (h3); + assert (status == 0); + status = dlclose (h2); + assert (status == 0); + h4 = load_dso (OBJ4, 4, &s4); + h3 = load_dso (OBJ3, 3, &s3); + h2 = load_dso (OBJ2, 2, &s2); + h1 = load_dso (OBJ1, 1, &s1); + + /* Set TLS vars; currently, lib1, lib2, lib3, and lib4 are all + loaded. */ + for (i = 1; i <= 4; i++) + s0 (i, 70 + i); + for (i = 1; i <= 4; i++) + s1 (i, 170 + i); + for (i = 1; i <= 4; i++) + s2 (i, 270 + i); + for (i = 1; i <= 4; i++) + s3 (i, 370 + i); + for (i = 1; i <= 4; i++) + s4 (i, 470 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1070 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1170 + i); + + use_it (0); /* main-breakpoint-8 */ + + /* Unload lib3, lib1, and lib4. */ + status = dlclose (h3); + assert (status == 0); + status = dlclose (h1); + assert (status == 0); + status = dlclose (h4); + assert (status == 0); + + /* Set TLS vars; currently, lib2 is loaded; lib1, lib3, and lib4 are + not. */ + for (i = 1; i <= 4; i++) + s0 (i, 80 + i); + for (i = 1; i <= 4; i++) + s2 (i, 280 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1080 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1180 + i); + + use_it (0); /* main-breakpoint-9 */ + + /* Load lib3, unload lib2, load lib4. */ + h3 = load_dso (OBJ3, 3, &s3); + status = dlclose (h2); + assert (status == 0); + h4 = load_dso (OBJ4, 4, &s4); + + /* Set TLS vars; currently, lib3 and lib4 are loaded; lib1 and lib2 + are not. */ + for (i = 1; i <= 4; i++) + s0 (i, 90 + i); + for (i = 1; i <= 4; i++) + s3 (i, 390 + i); + for (i = 1; i <= 4; i++) + s4 (i, 490 + i); + for (i = 1; i <= 4; i++) + s10 (i, 1090 + i); + for (i = 1; i <= 4; i++) + s11 (i, 1190 + i); + + use_it (0); /* main-breakpoint-10 */ + + /* Attempt to keep variables in the main program from being optimized + away. */ + use_it (tls_main_tbss_1); + use_it (tls_main_tbss_2); + use_it (tls_main_tdata_1); + use_it (tls_main_tdata_2); + + use_it (100); /* main-breakpoint-last */ + + return 0; +} diff --git a/gdb/testsuite/gdb.base/tls-dlobj.exp b/gdb/testsuite/gdb.base/tls-dlobj.exp new file mode 100644 index 00000000000..02f2ff81219 --- /dev/null +++ b/gdb/testsuite/gdb.base/tls-dlobj.exp @@ -0,0 +1,378 @@ +# Copyright 2024 Free Software Foundation, Inc. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# Test that the GDB-internal TLS link map to module id mapping code +# works correctly when debugging a program which is linked against +# shared objects and which also loads and unloads other shared objects +# in different orders. For targets which have GDB-internal TLS +# support, it'll check both GDB-internal TLS support as well as that +# provided by a helper library such as libthread_db. + +source $srcdir/$subdir/tls-common.exp.tcl + +require allow_shlib_tests + +standard_testfile + +set libsrc "${srcdir}/${subdir}/${testfile}-lib.c" + +# These will be dlopen'd: +set lib1obj [standard_output_file "${testfile}1-lib.so"] +set lib2obj [standard_output_file "${testfile}2-lib.so"] +set lib3obj [standard_output_file "${testfile}3-lib.so"] +set lib4obj [standard_output_file "${testfile}4-lib.so"] + +# These will be dynamically linked with the main program: +set lib10obj [standard_output_file "${testfile}10-lib.so"] +set lib11obj [standard_output_file "${testfile}11-lib.so"] + +# Due to problems with some versions of glibc, we expect some tests to +# fail due to TLS storage not being allocated/initialized. Test +# command CMD using regular expression RE, and use XFAIL instead of +# FAIL when the relevant RE is matched and COND is true when evaluated +# in the upper level. + +proc gdb_test_with_xfail { cmd re cond} { + gdb_test_multiple $cmd $cmd { + -re -wrap $re { + pass $gdb_test_name + } + -re -wrap "The inferior has not yet allocated storage for thread-local variables.*" { + if [ uplevel 1 [list expr $cond]] { + xfail $gdb_test_name + } else { + fail $gdb_test_name + } + } + } +} + +proc do_tests {force_internal_tls} { + clean_restart $::binfile + if ![runto_main] { + return + } + + if $force_internal_tls { + gdb_test_no_output "maint set force-internal-tls-address-lookup on" + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"] + gdb_continue_to_breakpoint "main-breakpoint-1" + + with_test_prefix "before assignments" { + gdb_test "print tls_main_tbss_1" ".* = 0" + gdb_test "print tls_main_tbss_2" ".* = 0" + gdb_test "print tls_main_tdata_1" ".* = 96" + gdb_test "print tls_main_tdata_2" ".* = 97" + + # For these tests, where we're attempting to access TLS vars + # in a dlopen'd library, but before assignment to any of the + # vars, so it could happen that storage hasn't been allocated + # yet. But it might also work. (When testing against MUSL, + # things just work; GLIBC ends to produce the TLS error.) So + # accept either the right answer or a TLS error message. + + set tlserr "The inferior has not yet allocated storage for thread-local variables.*" + foreach n {1 2 3 4} { + gdb_test "print tls_lib${n}_tbss_1" \ + "0|${tlserr}" + gdb_test "print tls_lib${n}_tbss_2" \ + "0|${tlserr}" + gdb_test "print tls_lib${n}_tdata_1" \ + "96|${tlserr}" + gdb_test "print tls_lib${n}_tdata_2" \ + "97|${tlserr}" + } + foreach n {10 11} { + gdb_test "print tls_lib${n}_tbss_1" ".* = 0" + gdb_test "print tls_lib${n}_tbss_2" ".* = 0" + gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}96" + gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}97" + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"] + gdb_continue_to_breakpoint "main-breakpoint-2" + + with_test_prefix "at main-breakpoint-2" { + gdb_test "print tls_main_tbss_1" ".* = 11" + gdb_test "print tls_main_tbss_2" ".* = 12" + gdb_test "print tls_main_tdata_1" ".* = 13" + gdb_test "print tls_main_tdata_2" ".* = 14" + + foreach n {1 2 3 4 10 11} { + gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}11" + gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}12" + gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}13" + gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}14" + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-3"] + gdb_continue_to_breakpoint "main-breakpoint-3" + + # At this point lib2 and lib3 have been unloaded. Also, TLS vars + # in remaining libraries have been changed. + + with_test_prefix "at main-breakpoint-3" { + gdb_test "print tls_main_tbss_1" ".* = 21" + gdb_test "print tls_main_tbss_2" ".* = 22" + gdb_test "print tls_main_tdata_1" ".* = 23" + gdb_test "print tls_main_tdata_2" ".* = 24" + + foreach n {1 4 10 11} { + gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}21" + gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}22" + gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}23" + gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}24" + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-4"] + gdb_continue_to_breakpoint "main-breakpoint-4" + + # lib3 has been loaded again; lib2 is the only one not loaded. + + with_test_prefix "at main-breakpoint-4" { + gdb_test "print tls_main_tbss_1" ".* = 31" + gdb_test "print tls_main_tbss_2" ".* = 32" + gdb_test "print tls_main_tdata_1" ".* = 33" + gdb_test "print tls_main_tdata_2" ".* = 34" + + set cond { $n == 3 } + foreach n {1 3 4 10 11} { + gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}31" $cond + gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}32" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}33" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}34" $cond + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-5"] + gdb_continue_to_breakpoint "main-breakpoint-5" + + # lib2 and lib3 are loaded; lib1 and lib4 are not. + + with_test_prefix "at main-breakpoint-5" { + gdb_test "print tls_main_tbss_1" ".* = 41" + gdb_test "print tls_main_tbss_2" ".* = 42" + gdb_test "print tls_main_tdata_1" ".* = 43" + gdb_test "print tls_main_tdata_2" ".* = 44" + + set cond { $n == 2 || $n == 3 } + foreach n {2 3 10 11} { + gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}41" $cond + gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}42" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}43" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}44" $cond + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-6"] + gdb_continue_to_breakpoint "main-breakpoint-6" + + # lib1, lib3 and lib4 are loaded; lib2 is not loaded. + + with_test_prefix "at main-breakpoint-6" { + gdb_test "print tls_main_tbss_1" ".* = 51" + gdb_test "print tls_main_tbss_2" ".* = 52" + gdb_test "print tls_main_tdata_1" ".* = 53" + gdb_test "print tls_main_tdata_2" ".* = 54" + + set cond { $n == 1 || $n == 3 || $n == 4} + foreach n {1 3 4 10 11} { + gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}51" $cond + gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}52" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}53" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}54" $cond + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-7"] + gdb_continue_to_breakpoint "main-breakpoint-7" + + # lib2 and lib3 are loaded; lib1 and lib4 are not. + + with_test_prefix "at main-breakpoint-7" { + gdb_test "print tls_main_tbss_1" ".* = 61" + gdb_test "print tls_main_tbss_2" ".* = 62" + gdb_test "print tls_main_tdata_1" ".* = 63" + gdb_test "print tls_main_tdata_2" ".* = 64" + + set cond { $n == 2 || $n == 3 } + foreach n {2 3 10 11} { + gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}61" $cond + gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}62" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}63" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}64" $cond + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-8"] + gdb_continue_to_breakpoint "main-breakpoint-8" + + # lib1, lib2, lib3, and lib4 are all loaded. + + with_test_prefix "at main-breakpoint-8" { + gdb_test "print tls_main_tbss_1" ".* = 71" + gdb_test "print tls_main_tbss_2" ".* = 72" + gdb_test "print tls_main_tdata_1" ".* = 73" + gdb_test "print tls_main_tdata_2" ".* = 74" + + foreach n {1 2 3 4 10 11} { + gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}71" + gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}72" + gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}73" + gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}74" + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-9"] + gdb_continue_to_breakpoint "main-breakpoint-9" + + # lib2 is loaded; lib1, lib3, and lib4 are not. + + with_test_prefix "at main-breakpoint-9" { + gdb_test "print tls_main_tbss_1" ".* = 81" + gdb_test "print tls_main_tbss_2" ".* = 82" + gdb_test "print tls_main_tdata_1" ".* = 83" + gdb_test "print tls_main_tdata_2" ".* = 84" + + foreach n {2 10 11} { + gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}81" + gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}82" + gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}83" + gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}84" + } + } + + gdb_breakpoint [gdb_get_line_number "main-breakpoint-10"] + gdb_continue_to_breakpoint "main-breakpoint-10" + + # lib3 and lib4 are loaded; lib1 and lib2 are not. + + with_test_prefix "at main-breakpoint-10" { + gdb_test "print tls_main_tbss_1" ".* = 91" + gdb_test "print tls_main_tbss_2" ".* = 92" + gdb_test "print tls_main_tdata_1" ".* = 93" + gdb_test "print tls_main_tdata_2" ".* = 94" + + set cond { $n == 3 || $n == 4 } + foreach n {3 4 10 11} { + gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}91" $cond + gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}92" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}93" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}94" $cond + } + } + + # gdb_interact + + set corefile ${::binfile}.core + set core_supported 0 + if { ![is_remote host] } { + set core_supported [gdb_gcore_cmd $corefile "save corefile"] + } + + # Finish test early if no core file was made. + if !$core_supported { + return + } + + clean_restart $::binfile + + set core_loaded [gdb_core_cmd $corefile "load corefile"] + if { $core_loaded == -1 } { + return + } + + with_test_prefix "core file" { + if $force_internal_tls { + gdb_test_no_output "maint set force-internal-tls-address-lookup on" + } + + gdb_test "print tls_main_tbss_1" ".* = 91" + gdb_test "print tls_main_tbss_2" ".* = 92" + gdb_test "print tls_main_tdata_1" ".* = 93" + gdb_test "print tls_main_tdata_2" ".* = 94" + + set cond { $n == 3 || $n == 4 } + foreach n {3 4 10 11} { + gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}91" $cond + gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}92" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}93" $cond + gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}94" $cond + } + } +} + +# Build shared objects for dlopen: +if { [gdb_compile_shlib $libsrc $lib1obj [list debug additional_flags=-DN=1]] != "" } { + untested "failed to compile shared object" + return -1 +} +if { [gdb_compile_shlib $libsrc $lib2obj [list debug additional_flags=-DN=2]] != "" } { + untested "failed to compile shared object" + return -1 +} +if { [gdb_compile_shlib $libsrc $lib3obj [list debug additional_flags=-DN=3]] != "" } { + untested "failed to compile shared object" + return -1 +} +if { [gdb_compile_shlib $libsrc $lib4obj [list debug additional_flags=-DN=4]] != "" } { + untested "failed to compile shared object" + return -1 +} + +# Build shared objects to link against main program: +if { [gdb_compile_shlib $libsrc $lib10obj [list debug additional_flags=-DN=10]] != "" } { + untested "failed to compile shared object" + return -1 +} +if { [gdb_compile_shlib $libsrc $lib11obj [list debug additional_flags=-DN=11]] != "" } { + untested "failed to compile shared object" + return -1 +} + +# Use gdb_compile_pthreads to build and link the main program for +# testing. It's also possible to run the tests using plain old +# gdb_compile, but this adds complexity with setting up additional +# KFAILs. (When run using GLIBC versions earlier than 2.34, a program +# that's not dynamically linked against libpthread will lack a working +# libthread_db, and, therefore, won't be able to access thread local +# storage without GDB-internal TLS support. Additional complications +# arise from when testing on x86_64 with -m32, which tends to work +# okay on GLIBC 2.34 and newer, but not older versions. It gets messy +# to properly sort out all of these cases.) +# +# This test was originally written to do it both ways, i.e. with both +# both gdb_compile and gdb_compile_pthreads, but the point of this +# test is to check that the link map address to TLS module id mapping +# code works correctly in programs which use lots of dlopen and +# dlclose calls in various orders - and that can be done using just +# gdb_compile_pthreads. + +if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \ + [list debug shlib_load \ + shlib=${lib10obj} \ + shlib=${lib11obj} \ + additional_flags=-DOBJ1=\"${lib1obj}\" \ + additional_flags=-DOBJ2=\"${lib2obj}\" \ + additional_flags=-DOBJ3=\"${lib3obj}\" \ + additional_flags=-DOBJ4=\"${lib4obj}\" \ + ]] != "" } { + untested "failed to compile" +} else { + foreach_with_prefix force_internal_tls $internal_tls_iters { + do_tests $force_internal_tls + } +} From patchwork Fri Oct 25 02:26:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 99527 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 B988E3858031 for ; Fri, 25 Oct 2024 03:39:02 +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 3AD0E3858D3C for ; Fri, 25 Oct 2024 03:35:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3AD0E3858D3C 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 3AD0E3858D3C 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=1729827325; cv=none; b=aJcP2jtKlJRE1qTSS2QmGMTxKYcc39yQpsPTH6dQHpA3vaSjY7aEB+2bYC7LRZvQvdDEsECLJ61rDh0FoEwjpVAxSVNUanKcI2p+8wWuqph9AdtrbZtuLDz5G3s6UQ5MmK5RO/4dHmoa5MbvOAkdGghz3eroCtadIHpyqgoR2PU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729827325; c=relaxed/simple; bh=Nj9U2z8rAvl1+biiztjdHkFop1uAOztEoCVb6V0YD/A=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=WEAc3vWQCWXrf8cTX42mWLr/O5rP8z9Lz/Yy//b5obA5WhItIsNHF9uxZ5i09TaUgJHec+As0ctTl23tfVrRcSTeQnWApuIOUBmmdrRq/H3S6K9VnsXKohmTbvV7kYeXwItkBHZDNXbcjwHtdI9tAJxv9HR/QZhEYuF0ZbQkKwU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729827316; 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=3yHPtV1bwv3ZtL2hMP0WEi+zxCfI0FHgmDVjQaMjFHE=; b=brUMjx66mH1J1t4e3NdLfgC4cKwkSALt7CddyBDmi0KBQ7YdNvp0okRBWDkbWXd7cBSpXj TQjqQ20YiY5pqt8gp5br2/cs/0x5yaA2/vPkeN3qRRHMKeJCofgMCR/lwjIowq262JA7dz O82Jrph7JLUdSgsnZf1+tft6ukP32Cs= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-500-ukEFTanAOEKxE5RVAeGoyg-1; Thu, 24 Oct 2024 23:35:15 -0400 X-MC-Unique: ukEFTanAOEKxE5RVAeGoyg-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D753319560A1 for ; Fri, 25 Oct 2024 03:35:14 +0000 (UTC) Received: from f41-1.lan (unknown [10.22.64.38]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5AA5D300018D; Fri, 25 Oct 2024 03:35:12 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Cc: Kevin Buettner Subject: [PATCH v3 11/11] Add TLS NEWS entry and document 'set force-internal-tls-address-lookup' command Date: Thu, 24 Oct 2024 19:26:29 -0700 Message-ID: <20241025033431.36274-12-kevinb@redhat.com> In-Reply-To: <20241025033431.36274-1-kevinb@redhat.com> References: <20241025033431.36274-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.0 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 --- gdb/NEWS | 20 ++++++++++++++++++ gdb/doc/gdb.texinfo | 50 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) Reviewed-By: Eli Zaretskii diff --git a/gdb/NEWS b/gdb/NEWS index 42b8a88fd8a..ef417202e80 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -65,6 +65,26 @@ the return value from the latest "stepOut" command, when appropriate. +* GDB-internal Thread Local Storage (TLS) support + + ** Linux targets for the x86_64, aarch64, ppc64, s390x, and riscv + architectures now have GDB-internal support for TLS address + lookup in addition to that traditionally provided by the + libthread_db library. This internal support works for programs + linked against either the GLIBC or MUSL C libraries. For + programs linked against MUSL, this new internal support provides + new debug functionality, allowing access to TLS variables, due to + the fact that MUSL does not implement the libthread_db library. + Internal TLS support is also useful in cross-debugging + situations, debugging statically linked binaries, and debugging + programs linked against GLIBC 2.33 and earlier, but which are not + linked against libpthread. + + ** The command 'maint set force-internal-tls-address-lookup on' may + be used to force the internal TLS lookup mechanisms to be used. + Otherwise, TLS lookup via libthread_db will still be preferred, + when available. + * New commands set style line-number foreground COLOR diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index eb2aff974bb..adb70f0d579 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4084,6 +4084,56 @@ When @samp{on} @value{GDBN} will print additional messages when threads are created and deleted. @end table +@cindex thread local storage +@cindex @acronym{TLS} +For some debugging targets, @value{GDBN} has support for accessing +variables that reside in Thread Local Storage (@acronym{TLS}). +@acronym{TLS} variables are similar to global variables, except that +each thread has its own copy of the variable. While often used in +multi-threaded programs, @acronym{TLS} variables can also be used in +programs without threads. The C library variable @var{errno} is, +perhaps, the most prominent example of a @acronym{TLS} variable that +is frequently used in non-threaded programs. For targets where +@value{GDBN} does not have good @acronym{TLS} support, printing or +changing the value of @var{errno} might not be directly possible. + +@sc{gnu}/Linux and FreeBSD targets have support for accessing +@acronym{TLS} variables. On @sc{gnu}/Linux, the helper library, +@code{libthread_db}, is used to help resolve the addresses of +@acronym{TLS} variables. Some FreeBSD and some @sc{gnu}/Linux targets +also have @value{GDBN}-internal @acronym{TLS} resolution code. +@sc{gnu}/Linux targets will attempt to use the @acronym{TLS} address +lookup functionality provided by @code{libthread_db}, but will fall +back to using its internal @acronym{TLS} support when +@code{libthread_db} is not available. This can happen in +cross-debugging scenarios or when debugging programs that are linked +in such a way that @code{libthread_db} support is unavailable - this +includes statically linked programs, linking against @acronym{GLIBC} +versions earlier than 2.34, but not with @code{libpthread}, and use of +other (non-@acronym{GLIBC}) C libraries. + +@table @code +@kindex maint set force-internal-tls-address-lookup +@kindex maint show force-internal-tls-address-lookup +@cindex internal @acronym{TLS} address lookup +@item maint set force-internal-tls-address-lookup +@itemx maint show force-internal-tls-address-lookup +Turns on or off forced use of @value{GDBN}-internal @acronym{TLS} +address lookup code. Use @code{on} to enable and @code{off} to +disable. The default for this setting is @code{off}. + +When disabled, @value{GDBN} will attempt to use a helper +@code{libthread_db} library if possible, but will fall back to use of +its own internal @acronym{TLS} address lookup mechanisms if necessary. + +When enabled, @value{GDBN} will only use @value{GDBN}'s internal +@acronym{TLS} address lookup mechanisms, if they exist. + +This command is only available for @sc{gnu}/Linux targets. Its +primary use is for testing - certain tests in the @value{GDBN} test +suite use this command to force use of internal TLS address lookup. +@end table + @node Forks @section Debugging Forks