From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id VnCEE3PjAWmqZg8AWB0awg (envelope-from ) for ; Wed, 29 Oct 2025 05:50:43 -0400 Authentication-Results: simark.ca; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=UGI2Eifm; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 400311E0BC; Wed, 29 Oct 2025 05:50:43 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_INVALID,DKIM_SIGNED,HTML_MESSAGE,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 1EAF01E057 for ; Wed, 29 Oct 2025 05:50:39 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7F4913858CDB for ; Wed, 29 Oct 2025 09:50:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7F4913858CDB Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=UGI2Eifm Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by sourceware.org (Postfix) with ESMTPS id 395C73858D20 for ; Wed, 29 Oct 2025 09:49:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 395C73858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 395C73858D20 Authentication-Results: server2.sourceware.org; arc=fail smtp.remote-ip=198.175.65.9 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1761731370; cv=fail; b=V6bymXV0Vt0DraJ4e6zDePJgYAQB0R3tEbJ1LOB9qguikgzzRsIdlfd3qG658L7bmiOvk+VXorGvUU6oda+MJvVn8CBQbXPQ8iQ6t5M7K57UvwLYoTXTN0YOGn17kMwPt6Kx9tvb7tjBMqQ8Fch7uRsT63JzYwkJmqH9XRWMlXY= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1761731370; c=relaxed/simple; bh=+s+lsd1Ysh/gtsJK6AcSLDbmhnhGdYBFO8ryrmPuA68=; h=DKIM-Signature:MIME-Version:From:To:Subject:Date:Message-ID: MIME-Version; b=K5WoyU3gQd5vflLLuuOqFl9CyrdsTn51feZUbiMnALuxNgzJwtNMzY60f9WUULGOy3k4iWhFHP916EC5S6N8q11jwgPhx442G2OlzwImVN2SoOA4bO8J55i/rl5UBuObuAhU6xEMCJtU4f97gQ+Vb3MRCDuda49bCPDHjGEyXMg= ARC-Authentication-Results: i=2; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 395C73858D20 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1761731371; x=1793267371; h=from:to:cc:subject:date:message-id:references: in-reply-to; bh=+s+lsd1Ysh/gtsJK6AcSLDbmhnhGdYBFO8ryrmPuA68=; b=UGI2EifmeawsowqUAHg0oKW6rYCHudaTb/BJx+xEf2sFlSt33Iz5BIKu QjNx/XOepEPcVXDwUZLneBfXyN6GjUGhy/MU08GXVY/sTqzshsN9plSAS bH9DJp24h0iTQTYPoXf8Sgg7prmkMfj/Tag6twbHIcqtGVaRICX3wudPn L2EZ9gSLh+QZQLF2QGGbRA48C8qoeFQK2QyRWLK342R40DuIlEw3wNLTK J1RE1S6SKJ5zxlROKiatm5v710ksCwXECOp2VuKfixhzPeA/hNPk+jDbg r7ZGls3Uud1Jcm2xwyUaeyRXKGzCtSXTo8Lu542fQjHiEFVAyYuk65C6l A==; X-CSE-ConnectionGUID: zZnpi4wGRZqsoLXI1O50jw== X-CSE-MsgGUID: /68XkHyvR0O4SxUYZUo/Tg== X-IronPort-AV: E=McAfee;i="6800,10657,11586"; a="86475783" X-IronPort-AV: E=Sophos;i="6.19,263,1754982000"; d="scan'208";a="86475783" Content-Type: multipart/mixed; boundary="===============0038220577384248253==" MIME-Version: 1.0 Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Oct 2025 02:49:30 -0700 X-CSE-ConnectionGUID: wyn8gAj3TriSAxg3lCIE0A== X-CSE-MsgGUID: QEG7j4ojR1qtofuxL1xU2A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.19,263,1754982000"; d="scan'208";a="216473581" Received: from orsmsx903.amr.corp.intel.com ([10.22.229.25]) by fmviesa001.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Oct 2025 02:49:29 -0700 Received: from ORSMSX902.amr.corp.intel.com (10.22.229.24) by ORSMSX903.amr.corp.intel.com (10.22.229.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.27; Wed, 29 Oct 2025 02:49:28 -0700 Received: from ORSEDG903.ED.cps.intel.com (10.7.248.13) by ORSMSX902.amr.corp.intel.com (10.22.229.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.27 via Frontend Transport; Wed, 29 Oct 2025 02:49:28 -0700 Received: from MW6PR02CU001.outbound.protection.outlook.com (52.101.48.13) by edgegateway.intel.com (134.134.137.113) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.27; Wed, 29 Oct 2025 02:49:28 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ycJlTGkzYkvnNB+bitFwYrzigTrhfVGyFCBR7r8/PXzwwbeqy46zEQfF2Ev+p+v7PgCSMeiN3SmxWUglKgmcRbJv1e/kpsQxIs2svvRtcQ/yUHBqXUvJ0m2Csd2TS6XAoZsdYpHisRS+QAynnBr4Ew3TaEuuksBnVWKNcNYI3WoJNRhl17RLj4EsOA0XKDoYLH2HjMJkb98R+K1Y71igkU5y3TqLRMKd1xVLUDxrNJU4dRlH0wTgTixfE8TD3PHZKDJWTsfWiQ/U0aSNb7u8jaFUOiNsqebmIYV5TC4cTd4OG+bQrAD8HceSwyPyyGiQcLHnJq02Dr43zUAr+7wRQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=yjfaWZGGaOz72zUthGU4dXIse86jEhAJL3I4WW4IC9Y=; b=R0SzJpFVyf6DiUsdhxAoyGyKbzhQuwaQ7IVYluvd3lwRbO2hRjJv0ax5IXWPD2CPvUPccutqd29dIonEn+tL6ZB46h6tZ2GHmjP1H3dtcXwCuancLEim8jUDEv05xGPXyqbolTQ28e9OWc0a4dzxDV2WVBsegMq2jloCfmJ2HEde/sVXi8+7XMVJKE5B0MLWUvrz1y9+DTr0fo4ku8d/W9iPqpNg5jHBX6pK9/L3SjLZOFjIEtuZsL6G1Faq6+3tByIuWlFL9AepnKSKJI5qJk8Tr0AjUwj9ZCXbChgW7mXOKlPEjajMYay1EixI9JvJW+Be3ysX2oudPRw6aTtgIw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none Received: from SN7PR11MB7638.namprd11.prod.outlook.com (2603:10b6:806:34b::22) by CH3PR11MB8155.namprd11.prod.outlook.com (2603:10b6:610:164::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9275.12; Wed, 29 Oct 2025 09:49:26 +0000 Received: from SN7PR11MB7638.namprd11.prod.outlook.com ([fe80::25b8:16dc:755e:34d1]) by SN7PR11MB7638.namprd11.prod.outlook.com ([fe80::25b8:16dc:755e:34d1%5]) with mapi id 15.20.9275.013; Wed, 29 Oct 2025 09:49:26 +0000 From: "Schimpe, Christina" To: Andrew Burgess , "gdb-patches@sourceware.org" CC: Eli Zaretskii Subject: RE: [PATCHv3] gdb: include NT_I386_TLS note in generated core files Thread-Topic: [PATCHv3] gdb: include NT_I386_TLS note in generated core files Thread-Index: AQHcPRIjE6uRMt/IuEabNtneBNXdELTY9Wdw Date: Wed, 29 Oct 2025 09:49:25 +0000 Message-ID: References: <730728a6858a3fcf4477ebe3895088c98f0fead2.1760450001.git.aburgess@redhat.com> In-Reply-To: <730728a6858a3fcf4477ebe3895088c98f0fead2.1760450001.git.aburgess@redhat.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: SN7PR11MB7638:EE_|CH3PR11MB8155:EE_ x-ms-office365-filtering-correlation-id: 55173c07-40a6-40b2-fe3d-08de16d07245 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230040|1800799024|366016|376014|13003099007|38070700021; x-microsoft-antispam-message-info: =?us-ascii?Q?UsRDE1bgh6VkHPSLoN3cedzhdmy9vFj3XXsc62kQc8lX4SYDFLG9vdkfKA01?= =?us-ascii?Q?egSSVXuU51nyUkHyD4Sb8w1NcC4p9TxpMpwXzPWCwN8kmUy2pHcT/81golXz?= =?us-ascii?Q?Wi4zMIcdjZjaI107ALsDEJsPw/jsK4vg5kB59CZNOuoVNiSZgZFqeZqO0W9g?= =?us-ascii?Q?BdT1RQggY+F2oef6daPxYuQ69bEaeHEgoZn3HPTsBI9lE4oi6DuFqFzR8Kkq?= =?us-ascii?Q?ZWj+xaGzGs47fyWQ3Y/ppR1rQ1f0dvu6t30IX7zsJHvuUbgrgynNoWzxeEYn?= =?us-ascii?Q?RokVy3DnacafKFUoesrdQ3ok3YnCxT6xGldZQjFb2w1ZhJOlmy1CD83n0qmx?= =?us-ascii?Q?BQih033iU48E4DM0hEpEuhBIhvtRhO0jYPnw5J7WWaMcG3GuTiM1fwFz5frG?= =?us-ascii?Q?lRA5ExO4ltacq3jNFy1qi12Y/zdDWVeRiJkezvJPoUG4df1pD3Hi3RCVKZJF?= =?us-ascii?Q?P49CXCk7gQSDxI8HL8tw8v+0rCaWAWtx3Ip+cIhHpbhLhrPYGcgQ1dBFmrot?= =?us-ascii?Q?GZRVyLXhXaZMXxQW7omYQ5XdrcQzExPxqsKlfPuU133XGzK21oduFZgsuOy3?= =?us-ascii?Q?a7IBDFI2mQ1HsLxqQrJlnlqLvcn3UuzO8hGbniczVH5kiZYDQk8voOKcOyiR?= =?us-ascii?Q?MYeOM38fHYzKsfQCXCnIY1c1GrBOIoAdYwgtTDZgAf5a/36qhjSi5eN7JtmJ?= =?us-ascii?Q?YudoW+RnTAYIbqs/H7BzSYjRdh+Bc7AM3qerR3q9wi42L2B4yOK4N2Qt+ij7?= =?us-ascii?Q?mn7M36ijpIN+R2EGFHfCEY9gUXrRqY46E/ro+Zetcegaky7ge1PjpzabXwmJ?= =?us-ascii?Q?CSFdlQJN3+a7VSHdVQaresjul/4QO2SBelQLc6xsgGxM3JyZ06QKfZc97FVq?= =?us-ascii?Q?OuSnKmO7Hh3BapDozyijKtkgXpcAhtUK8NbIkkpifyv1GiKyP4iiG1e4dBAc?= =?us-ascii?Q?mPrW5izMdH6kSVWa6BTXdHsC6JjGE7cMSQvtRHaaIzVKslOkWysth/4V3u1m?= =?us-ascii?Q?Uk65rV8/iNX6ivr4vj3GE+ffFty8RTl20cx8Dxr9WXTG87iSlzBsxGGGiWFm?= =?us-ascii?Q?OhKTFPEPDxM0PuJJ75F8OxRj+iqG8nE66VjHTYtLu769MQsUlsHWG4Y3TOZL?= =?us-ascii?Q?2zre0EBS9gZ1qBTkV6AUB2LiUxQl4Gc9I2M+PYNOLiTDDvmL/MhNjVQ38rsZ?= =?us-ascii?Q?vVp1cyJbOCB8x1+RDu9k0MqTpZxkFf+AlZ4Ul2O+XcQF/zPsae51qspA1s0K?= =?us-ascii?Q?fVE9vJKR89QOlabe6cTb6lTjUgThffzwHmbfQRFQFhNq8ngKm3l6NAIvhoNV?= =?us-ascii?Q?B9HlTZjxYrC9TXUtvNNrGplallWo5H/PmIUp21v0Z2g5/Js/iLXrpyEbnKtl?= =?us-ascii?Q?qUtvdFFSZx0zTTcFE0L+r/wUOSTIz+qNyrUhvnPkzNjCPsimgfSDZRneOPbg?= =?us-ascii?Q?e0tA8jhd0GDuCLpTv5VPqRm8J/0ku18uZxGq1CL0rsDY51q8avK17Q=3D=3D?= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SN7PR11MB7638.namprd11.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(376014)(13003099007)(38070700021); DIR:OUT; SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?FSyNqwfY8fdBcL72Vg1MJuA9eyZ7CtEIb/YXhR36/lWVeIiMUN21j9fmJTC3?= =?us-ascii?Q?i8w8gWI43YwPBZ2J+oyF8qYKZAZ/JjD15p4PiCvixIX/LjqFmqKAgbeiUt2k?= =?us-ascii?Q?WeQwnXVh+SGWEmhJYtqKSU8R3rAIZ8YLKKkTn4/KegBezxlGpManAlQVY6Ea?= =?us-ascii?Q?v/PS+16af4Oa6sq5hmnuFIXGLVSOdD5DjpANlycmB46PW1IiVP9+pMzBrEvw?= =?us-ascii?Q?6o+IDvxzcdlTm/OhAew2rSZ55szHBw4iiVaBVDXBgZsWvMUEYPXZKNMCK0Jy?= =?us-ascii?Q?hSAqNBbKkEIpm1K1nS298FBlhwTJ/4yCRqR68K9oHoIQtF/hUSJP1SqGVQ+N?= =?us-ascii?Q?XgvFnwQKTL/DomfZ4fIV6wFclmVbnyftR9MHcJDNQo/sozm1CqIMXTE7DzqC?= =?us-ascii?Q?i7SD3r2MbBJnc63fyQQfSIhNFYp98PFdOHT8Ijo0gsqCpzPQsRPBCV2BwJa8?= =?us-ascii?Q?MVAZJ8bSvnmdq6n2SH0SYoPSOGJ+f7JUHTvgW5gfL+HQwcPFsG1dRNpFV3Ce?= =?us-ascii?Q?eWMwAjFTk/dLbAkNZG54Qfru3qJx1lDH+L2ek7kDTeCRXHmaYmOE+7Vl7Alf?= =?us-ascii?Q?AGhzXElfyyOrmYPK+l2tMhNEJDhu5p7Ectg4QNdKKNi3TK5O/a5HuczvTrYp?= =?us-ascii?Q?IXB7mN6vDoW5GW6WLKIxryzU1PQgtgsnunAWfzMpm1HBHRSRGwVVS1DqjTCD?= =?us-ascii?Q?2OzChdsnxp5gMfAfmw/SeywGu58VaYd2TN9/6/tv3YMb+2CpEm6Gm6zUCCdg?= =?us-ascii?Q?HAUz/oA0jED7GORpidGEQ88Na2p24dGrW6VrSRsVi2vpg5nYZfcgaNSKQV4D?= =?us-ascii?Q?za+qS6HeQRBhpr3h1L3g0uRVyL4n1awDVhWYtB1xhXluZjQqBdjJPwYWX8pj?= =?us-ascii?Q?uVluX9URKTNcyhpxghRe6TbBh5bluQf8wHB/VMvnODN4SCC6eOorFgBZmiIW?= =?us-ascii?Q?qURZqELBqeEeWeSuxCLNIuuOaWBA3wd277ilsuOBtaeE1qVzacaY5SKGUYqQ?= =?us-ascii?Q?M059PCcnxfDSmoivcmeW3tihB4qQMEBdZcEC1NJtA7xciOjQ4YsuIB34QQ6G?= =?us-ascii?Q?2LpamT7pHagXaKUUg034vQtAoFiSBdTWwrr/NbeDVHVMJYuXVMAke+xbICBI?= =?us-ascii?Q?Lv5fL+gRfH4EuAhyI0tBuayw0+2Wrk4NWxGkbGCRcNCALVfDVMz9ykW2dN/E?= =?us-ascii?Q?OtoYoabinCRMSddjZXA2mfHks46X1eTmH2Pf7c/BtLSLjN3WTOFq1d3FXg/D?= =?us-ascii?Q?4r8jkHzslEf2yMmG5r+quAeMHekvTMV/t6kGOi/Y1SlgVX7dyJT7Y1gMLbYX?= =?us-ascii?Q?CGabcNK8LyUf6NDQ08O3B2xGweIBhbYi3bWLfuNKAYt59kRs4nHx/DKrIHOM?= =?us-ascii?Q?SIREFayEbs0GBL8HvCJzwImXjZ+snyH0q8RaDNhCiW/5BZMEgYRu3U3mgFrY?= =?us-ascii?Q?Mgj9kl1EUTgbDwh+yF6Qt0Saq8n55PF+hbwlCMBe9zL1WEhPBSfyeMay9atj?= =?us-ascii?Q?QfqrUYy1ss1W6AU1XpU1ENrObEQDCId/f7jC/6xnJ1ifudEuOIZDhsT835W5?= =?us-ascii?Q?zACcP4u+vEd3ixOEyVvZuM2T4SfpEP/J0RT6+FSH1wQFlTQC/x+09nbpokwy?= =?us-ascii?Q?Ig=3D=3D?= MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: SN7PR11MB7638.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 55173c07-40a6-40b2-fe3d-08de16d07245 X-MS-Exchange-CrossTenant-originalarrivaltime: 29 Oct 2025 09:49:25.8868 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: 1SXjHMYa9N1odIlLAe+EReZ/bVgrOotznd/shpU5139x561XooKxqHw3Z23HgNGzjlHTSfgBzSt+Mpt1DOCXx3Hl017dAjPF/I71cUxF+6A= X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR11MB8155 X-OriginatorOrg: intel.com 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~public-inbox=simark.ca@sourceware.org --===============0038220577384248253== Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Andrew,=20 Thank you for working on this. Please find my comments below. > -----Original Message----- > From: Andrew Burgess > Sent: Tuesday, October 14, 2025 3:54 PM > To: gdb-patches@sourceware.org > Cc: Andrew Burgess ; Eli Zaretskii > Subject: [PATCHv3] gdb: include NT_I386_TLS note in generated core files >=20 > In v3: >=20 > - Fixed doc issue that Eli pointed out. >=20 > - Rebased to current HEAD, no merged conflicts. >=20 > In v2: >=20 > - Rebased to current HEAD, resolved merge conflicts related to > recent i386 register changes. >=20 > - Updated test to take account of recent clean_restart changes. >=20 > - Retested. >=20 > --- >=20 > This commit extends GDB for x86/Linux to include the NT_I386_TLS note in > generated core files (i.e. created with `generate-core-file` or `gcore` > command). This note contains the 3 per-thread TLS related GDT (global > descriptor table) entries, and is present for i386 binaries, or those com= piled > on x86-64 with -m32. >=20 > The approach I have taken to achieve this, is to make the 3 GDT entries > available within 3 new registers. I added these registers to the > org.gnu.gdb.i386.linux target description feature, as this feature seemed > perfectly named. As the new registers are optional I don't see any harm = in > extending this existing feature. I did consider adding a new feature wit= h `tls` > in the name, but this seemed excessive given the existing feature. >=20 > Which GDT entries are used for TLS varies between i386 and x86-64 running > in 32-bit mode. As such the registers are named with suffixes 0, 1, and = 2, > and it is left to GDB or gdbserver, to find the correct GDT entries (base= d on > the precise target) and place the contents into these registers. >=20 > With this done, adding the relevant regset is sufficient to get the tls > contents emitted as a core file note. Support for emitting the note into= the > generated core file relies on some BFD changes which were made in an > earlier commit: >=20 > commit ea6ec00ff4520895735e4913cb90c933c7296f04 > Date: Fri Jul 25 19:51:58 2025 +0100 >=20 > bfd: support for NT_386_TLS notes >=20 > The three new registers are readable and writable. Writing to one of the > new registers will update the relevant kernel GDT entry. >=20 > Each TLS GDT is represented by a 'struct user_desc' (see 'man 2 > get_thread_area' for details), the first 4 bytes of each 'user_desc' > is the 'entry_number' field, this is the index of the GDT within the kern= el, > and cannot be modified. Attempts to write to this region of the register= will > be ignored, but will not give an error. >=20 > I did consider not including this part of the user_desc within the regist= er > value, but this becomes difficult when we consider remote targets, GDB > would then need to figure out what these indexes were so that the core fi= le > note could be generated. Sure, we probably could figure the correct inde= x > values out, but I figure, why bother, we can just pass them through in th= e > register and know for certain that we have the correct values. >=20 > For testing, there's a new test that covers the basic functionality, incl= uding > read/write access to the new registers, and checking that the NT_386_TLS > note is added to the core file, and that the note contents can be read by > GDB. >=20 > I also manually tested opening a core file generated from an old GDB (so = no > NT_386_TLS notes) using a GDB with this patch. This works fine, the new = tls > registers are not created as the NT_GDB_TDESC note (the target descriptio= n) > doesn't include the new registers. >=20 > Out of interest I also patched an old version of GDB to avoid creating th= e > NT_GDB_TDESC, and created a core file. This core file contained neither = the > NT_386_TLS nor NT_GDB_TDESC. When opening this core file with a > patched GDB, the new registers do show up, but their contents are given a= s > , which is exactly what we'd expect, GDB builds a target > description based on the architecture, the architecture says these regist= ers > should exist, but they are missing from the core file, hence, . >=20 > I also tested using a patched GDB with an old version of gdbserver, the n= ew > registers don't show up as the old gdbserver doesn't send them in its tar= get > description. And a core file created using the gcore command in such a > setup leaves no NT_386_TLS notes added, which is what we'd expect. >=20 > And I also tested a new gdbserver running with an old version of GDB. > As the new tls registers are now mentioned in the target description, the= n > obviously, the old GDB does see the registers, and present them to the us= er, > however GDB doesn't know how to use these registers to create a > NT_386_TLS, so that note isn't added to any core files. > Also, while a new GDB places the tls registers into the 'system' > group, an old GDB doesn't do this, so the registers end up in the 'genera= l' > group by default. This means they show up within 'info registers' output= . > This isn't ideal, but there's not much that can be done about this. >=20 > Overall, I feel the combinations of old and new tools has been tested, an= d > the behaviours are what we'd want or expect. >=20 > I'm tagging this commit with PR gdb/15591, even though this patch isn't > directly related. That bug is for improving GDB's testing of TLS support= in > core files. The test in this commit does do some very simple reading of = a > TLS variable, but there's only two threads, and one TLS variable, so it's= not > extensive. Additionally, the test in this commit is x86 only, so this sh= ould > not be considered a full resolution to that bug. But still, it's somethi= ng. >=20 > Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D15591 >=20 > Reviewed-By: Eli Zaretskii > --- > gdb/NEWS | 4 + > gdb/amd64-linux-nat.c | 26 +- > gdb/doc/gdb.texinfo | 11 +- > gdb/features/i386/32bit-linux.c | 7 + > gdb/features/i386/32bit-linux.xml | 5 + > gdb/i386-linux-nat.c | 21 ++ > gdb/i386-linux-tdep.c | 171 +++++++++- > gdb/i386-linux-tdep.h | 15 + > gdb/i386-tdep.h | 5 + > gdb/nat/amd64-linux.h | 29 ++ > gdb/nat/i386-linux.h | 10 + > gdb/nat/x86-linux.c | 44 +++ > gdb/nat/x86-linux.h | 15 + > gdb/testsuite/gdb.arch/i386-linux-tls-regs.c | 74 +++++ > .../gdb.arch/i386-linux-tls-regs.exp | 314 ++++++++++++++++++ > gdb/x86-linux-nat.c | 67 ++++ > gdb/x86-linux-nat.h | 17 + > gdbserver/linux-x86-low.cc | 99 ++++++ > 18 files changed, 928 insertions(+), 6 deletions(-) create mode 100644 > gdb/nat/amd64-linux.h create mode 100644 gdb/testsuite/gdb.arch/i386- > linux-tls-regs.c > create mode 100644 gdb/testsuite/gdb.arch/i386-linux-tls-regs.exp >=20 > diff --git a/gdb/NEWS b/gdb/NEWS > index b0146852c5c..04b653aa97c 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -158,6 +158,10 @@ qExecAndArgs > In systems that don't support linker namespaces, or if the inferior ha= sn't > started yet, these always return the integer 0. >=20 > +* The 'org.gnu.gdb.i386.linux' target description feature can now > + contain three additional registers which provide access to the TLS > + related GDT entries on i386 (and x86-64 when compiling with -m32). > + > * Add record full support for rv64gc architectures >=20 > * Debugging Linux programs that use AArch64 Guarded Control Stacks is > now diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c index > 4b23fd9de53..99d6ecbc57c 100644 > --- a/gdb/amd64-linux-nat.c > +++ b/gdb/amd64-linux-nat.c > @@ -38,6 +38,9 @@ > #include "x86-linux-nat.h" > #include "nat/linux-ptrace.h" > #include "nat/amd64-linux-siginfo.h" > +#include "nat/i386-linux.h" > + > +#include >=20 > /* This definition comes from prctl.h. Kernels older than 2.5.64 > do not have it. */ > @@ -89,7 +92,8 @@ static int amd64_linux_gregset32_reg_offset[] =3D > -1, /* PKEYS register PKRU */ > -1, /* SSP register. */ > -1, -1, /* fs/gs base registers. */ > - ORIG_RAX * 8 /* "orig_eax" */ > + ORIG_RAX * 8, /* "orig_eax" */ > + -1, -1, -1, /* TLS GDT regs: i386_tls_gdt_0...2. */ > }; >=20 >=20 >=20 >=20 > @@ -236,7 +240,13 @@ amd64_linux_nat_target::fetch_registers (struct > regcache *regcache, int regnum) >=20 > if (regnum =3D=3D -1 || !amd64_native_gregset_supplies_p (gdbarch, reg= num)) > { > - elf_fpregset_t fpregs; > + if (regnum =3D=3D -1 || i386_is_tls_regnum_p (regnum)) > + { > + if (tdep->i386_linux_tls) > + i386_fetch_tls_regs (regcache, tid, regnum); > + if (regnum !=3D -1) > + return; > + } >=20 > if (have_ptrace_getregset =3D=3D TRIBOOL_TRUE) > { > @@ -266,6 +276,8 @@ amd64_linux_nat_target::fetch_registers (struct > regcache *regcache, int regnum) > } > else > { > + elf_fpregset_t fpregs; > + > if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0) > perror_with_name (_("Couldn't get floating point status")); >=20 > @@ -308,7 +320,13 @@ amd64_linux_nat_target::store_registers (struct > regcache *regcache, int regnum) >=20 > if (regnum =3D=3D -1 || !amd64_native_gregset_supplies_p (gdbarch, reg= num)) > { > - elf_fpregset_t fpregs; > + if (regnum =3D=3D -1 || i386_is_tls_regnum_p (regnum)) > + { > + if (tdep->i386_linux_tls) > + i386_store_tls_regs (regcache, tid, regnum); > + if (regnum !=3D -1) > + return; > + } >=20 > if (have_ptrace_getregset =3D=3D TRIBOOL_TRUE) > { > @@ -337,6 +355,8 @@ amd64_linux_nat_target::store_registers (struct > regcache *regcache, int regnum) > } > else > { > + elf_fpregset_t fpregs; > + > if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0) > perror_with_name (_("Couldn't get floating point status")); >=20 > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index > e0fc0ff98ab..102e3bd1923 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -50314,8 +50314,15 @@ i386 Features > @samp{ymm0h} through @samp{ymm15h} for amd64 @end itemize >=20 > -The @samp{org.gnu.gdb.i386.linux} feature is optional. It should -descr= ibe > a single register, @samp{orig_eax}. > +The @samp{org.gnu.gdb.i386.linux} feature is optional. If the feature > +is present, then it should describe the 32 bit register, @samp{orig_eax}= . > + > +Additionally, the @samp{org.gnu.gdb.i386.linux} feature can optionally > +contain three 128 bit registers called @samp{i386_tls_gdt_0}, > +@samp{i386_tls_gdt_1}, and @samp{i386_tls_gdt_2}. Each of these > +registers contains one 16 byte @samp{struct user_desc} (see @kbd{man > +2 get_thread_area}) object which describes one of the three TLS related > +GDT entries. >=20 > The @samp{org.gnu.gdb.i386.segments} feature is optional. It should > describe two system registers: @samp{fs_base} and @samp{gs_base}. > diff --git a/gdb/features/i386/32bit-linux.c b/gdb/features/i386/32bit- > linux.c index 3289f07d332..6fba8a6880b 100644 > --- a/gdb/features/i386/32bit-linux.c > +++ b/gdb/features/i386/32bit-linux.c > @@ -9,7 +9,14 @@ create_feature_i386_32bit_linux (struct target_desc > *result, long regnum) > struct tdesc_feature *feature; >=20 > feature =3D tdesc_create_feature (result, "org.gnu.gdb.i386.linux"); > + tdesc_type *element_type; > + element_type =3D tdesc_named_type (feature, "uint32"); > + tdesc_create_vector (feature, "i386_tls_gdt_reg", element_type, 4); > + > regnum =3D 41; > tdesc_create_reg (feature, "orig_eax", regnum++, 1, NULL, 32, "int"); > + tdesc_create_reg (feature, "i386_tls_gdt_0", regnum++, 1, "system", > + 128, "i386_tls_gdt_reg"); tdesc_create_reg (feature, > + "i386_tls_gdt_1", regnum++, 1, "system", 128, "i386_tls_gdt_reg"); > + tdesc_create_reg (feature, "i386_tls_gdt_2", regnum++, 1, "system", > + 128, "i386_tls_gdt_reg"); > return regnum; > } > diff --git a/gdb/features/i386/32bit-linux.xml b/gdb/features/i386/32bit- > linux.xml > index 0bfc0bc5563..7de3198b7da 100644 > --- a/gdb/features/i386/32bit-linux.xml > +++ b/gdb/features/i386/32bit-linux.xml > @@ -8,4 +8,9 @@ > name=3D"org.gnu.gdb.i386.linux"> > > + > + + name=3D"i386_tls_gdt_0" bitsize=3D"128" type=3D"i386_tls_gdt_reg" > + group=3D"system" /> + type=3D"i386_tls_gdt_reg" group=3D"system" /> + bitsize=3D"128" type=3D"i386_tls_gdt_reg" group=3D"system" /> > > diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c index > f5112d2b868..657fc52595c 100644 > --- a/gdb/i386-linux-nat.c > +++ b/gdb/i386-linux-nat.c > @@ -447,6 +447,8 @@ store_fpxregs (const struct regcache *regcache, int > tid, int regno) void i386_linux_nat_target::fetch_registers (struct reg= cache > *regcache, int regno) { > + struct gdbarch *gdbarch =3D regcache->arch (); const i386_gdbarch_tde= p > + *tdep =3D gdbarch_tdep (gdbarch); > pid_t tid; >=20 > /* Use the old method of peeking around in `struct user' if the @@ -47= 0,6 > +472,9 @@ i386_linux_nat_target::fetch_registers (struct regcache > *regcache, int regno) > zero. */ > if (regno =3D=3D -1) > { > + if (tdep->i386_linux_tls) > + i386_fetch_tls_regs (regcache, tid, regno); > + > fetch_regs (regcache, tid); >=20 > /* The call above might reset `have_ptrace_getregs'. */ @@ -514,6 > +519,12 @@ i386_linux_nat_target::fetch_registers (struct regcache > *regcache, int regno) > return; > } >=20 > + if (tdep->i386_linux_tls && i386_is_tls_regnum_p (regno)) > + { > + i386_fetch_tls_regs (regcache, tid, regno); > + return; > + } > + > internal_error (_("Got request for bad register number %d."), regno); = } >=20 > @@ -523,6 +534,8 @@ i386_linux_nat_target::fetch_registers (struct > regcache *regcache, int regno) void i386_linux_nat_target::store_regist= ers > (struct regcache *regcache, int regno) { > + struct gdbarch *gdbarch =3D regcache->arch (); const i386_gdbarch_tde= p > + *tdep =3D gdbarch_tdep (gdbarch); > pid_t tid; >=20 > /* Use the old method of poking around in `struct user' if the @@ -545= ,6 > +558,8 @@ i386_linux_nat_target::store_registers (struct regcache > *regcache, int regno) > store_fpxregs can fail, and return zero. */ > if (regno =3D=3D -1) > { > + if (tdep->i386_linux_tls) > + i386_store_tls_regs (regcache, tid, regno); > store_regs (regcache, tid, regno); > if (store_xstateregs (regcache, tid, regno)) > return; > @@ -578,6 +593,12 @@ i386_linux_nat_target::store_registers (struct > regcache *regcache, int regno) > return; > } >=20 > + if (tdep->i386_linux_tls && i386_is_tls_regnum_p (regno)) > + { > + i386_store_tls_regs (regcache, tid, regno); > + return; > + } > + > internal_error (_("Got request to store bad register number %d."), reg= no); > } >=20 >=20 >=20 > diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index > 34e13912098..5456663f2a7 100644 > --- a/gdb/i386-linux-tdep.c > +++ b/gdb/i386-linux-tdep.c > @@ -59,7 +59,7 @@ static int > i386_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum, > const struct reggroup *group) > { > - if (regnum =3D=3D I386_LINUX_ORIG_EAX_REGNUM) > + if (regnum =3D=3D I386_LINUX_ORIG_EAX_REGNUM || i386_is_tls_regnum_p > + (regnum)) > return (group =3D=3D system_reggroup > || group =3D=3D save_reggroup > || group =3D=3D restore_reggroup); > @@ -1047,6 +1047,7 @@ int i386_linux_gregset_reg_offset[] =3D > -1, /* SSP register. */ > -1, -1, /* fs/gs base registers. */ > 11 * 4, /* "orig_eax" */ > + -1, -1, -1, /* TLS GDT regs: i386_tls_gdt_0...2. */ > }; >=20 > /* Mapping between the general-purpose registers in `struct @@ -1163,6 > +1164,81 @@ i386_linux_collect_xstateregset (const struct regset *regset, > i387_collect_xsave (regcache, regnum, xstateregs, 1); } >=20 > +/* Within a tdep file we don't have access to system headers. This > + structure is a clone of 'struct user_desc' from 'asm/ldt.h' on x86 > + GNU/Linux systems. See 'see man 2 get_thread_area' on a suitable x86 > + machine for more details. */ > + > +struct x86_user_desc { > + uint32_t entry_number; > + uint32_t base_addr; > + uint32_t limit; > + > + /* In the actual struct, these flags are a series of 1-bit separate > + flags. But we don't need that level of insight for the > + processing we do in GDB, so just make it a single field. */ > + uint32_t flags; > +}; > + > +/* Supply the 3 tls related registers from BUFFER (length LEN) into > + REGCACHE. The REGSET and REGNUM are ignored, all three registers are > + always supplied from BUFFER. */ > + > +static void > +i386_linux_supply_tls_regset (const struct regset *regset, > + struct regcache *regcache, int regnum, > + const void *buffer, size_t len) { Nit: const struct regset *regset =3D> const regset *regset There are some more occurrences in this patch, where the struct keyword cou= ld be omitted, but=20 I'll just comment once here, and leave it up to you to fix this. I am not s= ure what the common=20 guideline is but I personally prefer to omit it. > + struct gdbarch *gdbarch =3D regcache->arch (); > + i386_gdbarch_tdep *tdep =3D gdbarch_tdep > (gdbarch); > + > + if (!tdep->i386_linux_tls) > + return; > + > + gdb_assert (len =3D=3D sizeof (struct x86_user_desc) * 3); > + > + for (int i =3D 0; i < 3; ++i) > + { > + int tls_regno =3D I386_LINUX_TLS_GDT_0 + i; > + > + gdb_assert (regcache->register_size (tls_regno) > + =3D=3D sizeof (struct x86_user_desc)); > + > + regcache->raw_supply (tls_regno, buffer); > + buffer =3D static_cast (buffer) + 1; > + } > +} > + > +/* Collect the 3 tls related registers from REGCACHE, placing the result= s > + in to BUFFER (length LEN). The REGSET and REGNUM are ignored, all > three > + registers are always collected from REGCACHE. */ > + > +static void > +i386_linux_collect_tls_regset (const struct regset *regset, > + const struct regcache *regcache, > + int regnum, void *buffer, size_t len) { > + struct gdbarch *gdbarch =3D regcache->arch (); > + i386_gdbarch_tdep *tdep =3D gdbarch_tdep > (gdbarch); > + > + if (!tdep->i386_linux_tls) > + return; > + > + gdb_assert (len =3D=3D sizeof (struct x86_user_desc) * 3); > + > + for (int i =3D 0; i < 3; ++i) > + { > + struct x86_user_desc desc; > + int tls_regno =3D I386_LINUX_TLS_GDT_0 + i; > + > + gdb_assert (regcache->register_size (tls_regno) =3D=3D sizeof > + (desc)); > + > + regcache->raw_collect (tls_regno, &desc); > + memcpy (buffer, &desc, sizeof (desc)); > + buffer =3D static_cast (buffer) + 1; > + } > +} > + > /* Register set definitions. */ >=20 > static const struct regset i386_linux_xstateregset =3D @@ -1172,6 +1248,= 65 > @@ static const struct regset i386_linux_xstateregset =3D > i386_linux_collect_xstateregset > }; >=20 > +static const struct regset i386_linux_tls_regset =3D > + { > + NULL, > + i386_linux_supply_tls_regset, > + i386_linux_collect_tls_regset > + }; > + > +/* Helper for i386_linux_iterate_over_regset_sections. Should we > + visit the NT_386_TLS note? If REGCACHE is NULL then we are reading > + the notes from the corefile, so we always visit the note. If > + REGCACHE is not NULL, in this case we are creating a corefile. In > + this case, we only visit the note if all the TLS registers are > + valid, and their base address and limit are not zero, this mirrors > + the kernel behaviour where the TLS note is elided when the TLS GDT > + entries have not been set. > + > + Only call for architectures where i386_gdbarch_tdep::i386_linux_tls > + is true. */ > + > +static bool > +should_visit_i386_tls_note (const struct regcache *regcache) { > + if (regcache =3D=3D nullptr) > + return true; > + > + /* Check the pre-condition. */ > + struct gdbarch *gdbarch =3D regcache->arch (); i386_gdbarch_tdep *tde= p > + =3D gdbarch_tdep (gdbarch); gdb_assert > + (tdep->i386_linux_tls); > + > + for (int i =3D 0; i < 3; ++i) > + { > + int tls_regno =3D I386_LINUX_TLS_GDT_0 + i; > + > + /* If we failed to read any of the registers then we'll not be > + able to emit valid note. */ > + if (regcache->get_register_status (tls_regno) !=3D REG_VALID) > + return false; > + > + /* As i386_gdbarch_tdep::i386_linux_tls is true, the registers > + must be the right size. The flag is only set true when this > + condition holds. */ > + gdb_assert (regcache->register_size (tls_regno) > + =3D=3D sizeof (struct x86_user_desc)); > + > + /* Read the TLS GDT entry. If it is in use then we want to > + write the NT_386_TLS note. */ > + struct x86_user_desc ud; > + regcache->raw_collect (tls_regno, &ud); > + if (ud.base_addr !=3D 0 && ud.limit !=3D 0) > + return true; > + } > + > + /* Made it through the loop without finding any in-use TLS related > + GDT entries. No point creating the NT_386_TLS note, the kernel > + doesn't. */ > + return false; > +} > + > /* Iterate over core file register note sections. */ >=20 > static void > @@ -1193,6 +1328,9 @@ i386_linux_iterate_over_regset_sections (struct > gdbarch *gdbarch, > cb_data); > else > cb (".reg2", 108, 108, &i386_fpregset, NULL, cb_data); > + > + if (tdep->i386_linux_tls && should_visit_i386_tls_note (regcache)) > + cb (".reg-i386-tls", 48, 48, &i386_linux_tls_regset, nullptr, > + cb_data); > } >=20 > /* Linux kernel shows PC value after the 'int $0x80' instruction even if= @@ - > 1272,6 +1410,37 @@ i386_linux_init_abi (struct gdbarch_info info, struct > gdbarch *gdbarch) > if (!valid_p) > return; >=20 > + /* Helper function. Look for TLS_REG_NAME in I386_FEATURE (with the > + associated LOCAL_TDESC_DATA), and if the register is found assign i= t > + TLS_REGNO. Return true if the register is found, and it is the siz= e > + of 'struct user_desc' (see man 2 get_thread_area), otherwise, retur= n > + false. */ Whitespace nit: 3 whitespaces after "Helper function.", it should only be 2= whitespaces. > + static const auto valid_tls_reg > + =3D [] (const struct tdesc_feature *i386_feature, > + struct tdesc_arch_data *local_tdesc_data, > + const char *tls_reg_name, int tls_regno) -> bool > + { > + static constexpr int required_reg_size > + =3D sizeof (struct x86_user_desc) * HOST_CHAR_BIT; > + return (tdesc_numbered_register (i386_feature, local_tdesc_data, > + tls_regno, tls_reg_name) > + && (tdesc_register_bitsize (i386_feature, tls_reg_name) > + =3D=3D required_reg_size)); > + }; > + > + /* Check all the expected tls related registers are found, and are the > + correct size. If they are then mark the tls feature as being activ= e > + in TDEP. Otherwise, leave the feature as deactivated. */ > + valid_p =3D (valid_tls_reg (feature, tdesc_data, "i386_tls_gdt_0", > + I386_LINUX_TLS_GDT_0) > + && valid_tls_reg (feature, tdesc_data, "i386_tls_gdt_1", > + I386_LINUX_TLS_GDT_1) > + && valid_tls_reg (feature, tdesc_data, "i386_tls_gdt_2", > + I386_LINUX_TLS_GDT_2)); > + > + if (valid_p) > + tdep->i386_linux_tls =3D true; > + > /* Add the %orig_eax register used for syscall restarting. */ > set_gdbarch_write_pc (gdbarch, i386_linux_write_pc); >=20 > diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h index > 8a1a2447776..e75e53aba95 100644 > --- a/gdb/i386-linux-tdep.h > +++ b/gdb/i386-linux-tdep.h > @@ -39,6 +39,13 @@ enum i386_linux_regnum > is supposed to restart. */ > I386_LINUX_ORIG_EAX_REGNUM =3D I386_NUM_REGS, >=20 > + /* Register numbers for the three TLS GDT registers. These contain th= e > + 'struct user_desc' (see 'man 2 get_thread_area') values for the thr= ee > + TLS related Global Descriptor Table entries. */ > + I386_LINUX_TLS_GDT_0, I386_LINUX_TLS_GDT_1, > I386_LINUX_TLS_GDT_2, > + > /* Total number of registers for GNU/Linux. */ > I386_LINUX_NUM_REGS >=20 > @@ -61,4 +68,12 @@ extern bool i386_linux_core_read_x86_xsave_layout > (struct gdbarch *gdbarch, >=20 > extern int i386_linux_gregset_reg_offset[]; >=20 > +/* Return true if REGNUM is one of the 3 tls gdt registers. */ > + > +static inline bool > +i386_is_tls_regnum_p (int regnum) > +{ > + return regnum >=3D I386_LINUX_TLS_GDT_0 && regnum <=3D > +I386_LINUX_TLS_GDT_2; } > + > #endif /* GDB_I386_LINUX_TDEP_H */ > diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index > cfe0d7383d6..ad355eb597a 100644 > --- a/gdb/i386-tdep.h > +++ b/gdb/i386-tdep.h > @@ -240,6 +240,11 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base > struct type *i386_zmm_type =3D nullptr; > struct type *i387_ext_type =3D nullptr; >=20 > + /* If the registers containing the i386 Linux TLS related global > + descriptor table information are available. This is used to decide > + whether to add the NT_386_TLS note to the core file or not. */ > + bool i386_linux_tls =3D false; > + > /* Process record/replay target. */ > /* The map for registers because the AMD64's registers order > in GDB is not same as I386 instructions. */ diff --git a/gdb/nat/a= md64- > linux.h b/gdb/nat/amd64-linux.h new file mode 100644 index > 00000000000..1d5bf573829 > --- /dev/null > +++ b/gdb/nat/amd64-linux.h > @@ -0,0 +1,29 @@ > +/* Native-dependent code for GNU/Linux amd64. > + > + Copyright (C) 2025 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + 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 > + . */ > + > +#ifndef GDB_NAT_AMD64_LINUX_H > +#define GDB_NAT_AMD64_LINUX_H > + > +/* See nat/i386-linux.h for a full description of this constant. This i= s > + the version used when GDB is compiled for amd64, and is running an > + executable compiled with -m32. */ > + > +static inline constexpr int i386_initial_tls_gdt =3D 12; > + > +#endif /* GDB_NAT_AMD64_LINUX_H */ > diff --git a/gdb/nat/i386-linux.h b/gdb/nat/i386-linux.h index > d80e0f999bf..b99f0a02418 100644 > --- a/gdb/nat/i386-linux.h > +++ b/gdb/nat/i386-linux.h > @@ -34,4 +34,14 @@ > variable. */ > extern tribool have_ptrace_getfpxregs; >=20 > +/* This constant defines the first GDT (Global Descriptor Table) entry > + that the kernel allocates for holding TLS descriptors. There are thr= ee > + entries, starting at this index which can be accessed using the > + PTRACE_GET_THREAD_AREA and PTRACE_SET_THREAD_AREA ptrace > calls. This > + constant is only valid for true i386 kernels. For amd64 kernels > + running in 32-bit mode (i.e. executables compiled -m32) there is a > + different constant, see nat/amd64-linux.h. */ > + > +static inline constexpr int i386_initial_tls_gdt =3D 6; > + > #endif /* GDB_NAT_I386_LINUX_H */ > diff --git a/gdb/nat/x86-linux.c b/gdb/nat/x86-linux.c index > 55158268970..017fe1314ad 100644 > --- a/gdb/nat/x86-linux.c > +++ b/gdb/nat/x86-linux.c > @@ -28,6 +28,12 @@ > #include "nat/gdb_ptrace.h" > #include >=20 > +#ifndef __x86_64__ > +#include "nat/i386-linux.h" > +#else > +#include "nat/amd64-linux.h" > +#endif > + > /* Per-thread arch-specific data we want to keep. */ >=20 > struct arch_lwp_info > @@ -185,3 +191,41 @@ x86_check_ssp_support (const int tid) >=20 > return true; > } > + > +/* See nat/x86-linux.h. */ > + > +bool > +i386_ptrace_get_tls_data (int pid, gdb::array_view > +buffer) { > + gdb_assert (buffer.size () =3D=3D 3); > + > + for (int i =3D 0; i < 3; ++i) > + { > + void *addr =3D (void *) (uintptr_t) (i386_initial_tls_gdt + i); > + void *data =3D buffer.slice (i, 1).data (); > + > + if (ptrace (PTRACE_GET_THREAD_AREA, pid, addr, data) < 0) > + return false; > + } > + > + return true; > +} > + > +/* See nat/x86-linux.h. */ > + > +bool > +i386_ptrace_set_tls_data (int pid, gdb::array_view > +buffer) { > + gdb_assert (buffer.size () =3D=3D 3); > + > + for (int i =3D 0; i < 3; ++i) > + { > + void *addr =3D (void *) (uintptr_t) (i386_initial_tls_gdt + i); > + void *data =3D buffer.slice (i, 1).data (); > + > + if (ptrace (PTRACE_SET_THREAD_AREA, pid, addr, data) < 0) > + return false; > + } > + > + return true; > +} > diff --git a/gdb/nat/x86-linux.h b/gdb/nat/x86-linux.h index > 1783aae05d0..cebe105b294 100644 > --- a/gdb/nat/x86-linux.h > +++ b/gdb/nat/x86-linux.h > @@ -21,6 +21,7 @@ > #define GDB_NAT_X86_LINUX_H >=20 > #include "nat/linux-nat.h" > +#include >=20 > /* Set whether our local mirror of LWP's debug registers has been > changed since the values were last written to the thread. Nonzero @@= - > 79,4 +80,18 @@ extern x86_linux_arch_size x86_linux_ptrace_get_arch_size > (int tid); >=20 > extern bool x86_check_ssp_support (const int tid); >=20 > +/* Get the three TLS related GDT (Global Descriptor Table) entries from > + the kernel for thread PID, placing the results into BUFFER, an array = of > + length 3. */ > + > +extern bool i386_ptrace_get_tls_data > + (int pid, gdb::array_view buffer); > + > +/* Store the three TLS related GDT (Global Descriptor Table) entries hel= d > + in BUFFER back into the kernel for thread PID. BUFFER must have a > + length of three. */ > + > +extern bool i386_ptrace_set_tls_data > + (int pid, gdb::array_view buffer); > + > #endif /* GDB_NAT_X86_LINUX_H */ > diff --git a/gdb/testsuite/gdb.arch/i386-linux-tls-regs.c > b/gdb/testsuite/gdb.arch/i386-linux-tls-regs.c > new file mode 100644 > index 00000000000..420d1566f20 > --- /dev/null > +++ b/gdb/testsuite/gdb.arch/i386-linux-tls-regs.c Given that there are a number of test files which are linux specific but do= n't have "-linux-" in their name, I wonder if there is any particular reason wh= y you chose it for the testfiles in this patch. > @@ -0,0 +1,74 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2025 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 > + > +static pthread_barrier_t barrier; > + > +static __thread int local_var =3D 0; > + > +volatile int wait_for_gdb_p =3D 1; > + > +volatile int should_dump_core_p =3D 1; > + > +void > +crash_func (void) > +{ > + if (should_dump_core_p) > + abort (); > +} > + > +void > +spin_forever (void) > +{ > + while (wait_for_gdb_p) > + sleep (1); > +} > + > +void * > +thread_func (void *arg) > +{ > + local_var =3D *((int*) arg); > + > + pthread_barrier_wait (&barrier); > + > + spin_forever (); > +} > + > +int > +main (void) > +{ > + pthread_t thr; > + > + if (pthread_barrier_init (&barrier, NULL, 2) !=3D 0) > + abort (); > + > + local_var =3D 1; > + int i =3D 2; > + if (pthread_create (&thr, NULL, thread_func, &i) !=3D 0) > + abort (); > + > + pthread_barrier_wait (&barrier); > + > + crash_func (); > + > + spin_forever (); > + > + return 0; > +} > diff --git a/gdb/testsuite/gdb.arch/i386-linux-tls-regs.exp > b/gdb/testsuite/gdb.arch/i386-linux-tls-regs.exp > new file mode 100644 > index 00000000000..199c8d2315e > --- /dev/null > +++ b/gdb/testsuite/gdb.arch/i386-linux-tls-regs.exp > @@ -0,0 +1,314 @@ > +# Copyright 2025 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 . > + > +# Check that the TLS GDT registers are available for i386 executable. > + > +require {is_any_target "i?86-*-linux*" "x86_64-*-linux*"} > + > +standard_testfile > + > +set options {debug pthreads} > +if {![istarget "i386-*-*"]} { > + lappend options "additional_flags=3D-m32" > +} > + > +if { [build_executable "failed to prepare" $testfile $srcfile $options] = } { > + return > +} > + > +# Start an inferior and check we can read and modify the TLS registers. > +proc_with_prefix test_tls_reg_availability {} { > + clean_restart $::testfile > + > + if {![runto_main]} { > + return -1 > + } I think we could remove the -1 here. > + set tls_reg_vals { "" "" "" } > + gdb_test_multiple "info registers system" "check for TLS regs" { > + -re "^info registers system\r\n" { > + exp_continue > + } > + -re "^i386_tls_gdt_(\\d) \\{($::hex), ($::hex), ($::hex), > ($::hex)\\}\r\n" { > + set idx $expect_out(1,string) > + set val0 $expect_out(2,string) > + set val1 $expect_out(3,string) > + set val2 $expect_out(4,string) > + set val3 $expect_out(5,string) > + set val [list $val0 $val1 $val2 $val3] > + set tls_reg_vals [lreplace $tls_reg_vals $idx $idx $val] > + exp_continue > + } > + -re "^$::gdb_prompt $" { > + gdb_assert {[lsearch -exact $tls_reg_vals ""] =3D=3D -1} > $gdb_test_name > + } > + -re "^\[^\r\n\]+\r\n" { > + exp_continue > + } > + } > + > + if { [lindex $tls_reg_vals 0] !=3D [lindex $tls_reg_vals 1] } { > + set new_vals [lindex $tls_reg_vals 0] > + set old_vals [lindex $tls_reg_vals 1] > + > + set val0 [lindex $old_vals 0] > + set val1 [lindex $new_vals 1] > + set val2 [lindex $new_vals 2] > + set val3 [lindex $new_vals 3] > + > + set new_val_str "{$val0, $val1, $val2, $val3}" > + > + gdb_test_no_output "set \$i386_tls_gdt_1 =3D $new_val_str" > + set re [string_to_regexp $new_val_str] > + gdb_test "print /x \$i386_tls_gdt_1" " =3D $re" > + } > + > + gdb_test_no_output "set should_dump_core_p=3D0" > + gdb_test_no_output "set wait_for_gdb_p=3D0" > + > + gdb_continue_to_end "" continue true } > + > +# Start GDB using global BINFILE, load COREFILE (which must match # > +BINFILE), and check that the core has two threads, that the TLS # > +registers are visible in both threads, and that the TLS register # > +values are different in each thread. > +proc load_core_and_test_tls_regs { corefile } { > + clean_restart $::testfile > + > + gdb_core_cmd $corefile "load corefile" > + > + gdb_test "info threads" \ > + [multi_line \ > + "\\*\\s+1\\s+Thread \[^\r\n\]+" \ > + "\\s+2\\s+Thread \[^\r\n\]+"] \ > + "check for two threads" > + > + # Record the TLS values in thread 1. > + set tls_reg_vals_thr_1 { "" "" "" } > + gdb_test_multiple "info registers system" "check for TLS regs thread= 1" { > + -re "^info registers system\r\n" { > + exp_continue > + } > + -re "^i386_tls_gdt_(\\d) (\\{$::hex, $::hex, $::hex, $::hex\\})\r\n" { > + set idx $expect_out(1,string) > + set val $expect_out(2,string) > + set tls_reg_vals_thr_1 [lreplace $tls_reg_vals_thr_1 $idx $idx $val= ] > + exp_continue > + } > + -re "^$::gdb_prompt $" { > + gdb_assert {[lsearch -exact $tls_reg_vals_thr_1 ""] =3D=3D -1} > $gdb_test_name > + } > + -re "^\[^\r\n\]+\r\n" { > + exp_continue > + } > + } > + > + # Check a TLS variable in thread 1. > + gdb_test "print local_var" " =3D 1" \ > + "check TLS variable in thread 1" > + > + # Switch to thread 2 and confirm the values are different. > + gdb_test "thread 2" > + > + set tls_reg_vals_thr_2 { "" "" "" } > + gdb_test_multiple "info registers system" "check for TLS regs thread= 2" { > + -re "^info registers system\r\n" { > + exp_continue > + } > + -re "^i386_tls_gdt_(\\d) (\\{$::hex, $::hex, $::hex, $::hex\\})\r\n" { > + set idx $expect_out(1,string) > + set val $expect_out(2,string) > + set tls_reg_vals_thr_2 \ > + [lreplace $tls_reg_vals_thr_2 $idx $idx $val] > + exp_continue > + } > + -re "^$::gdb_prompt $" { > + gdb_assert {[lsearch -exact $tls_reg_vals_thr_2 ""] =3D=3D -1} \ > + $gdb_test_name > + } > + -re "^\[^\r\n\]+\r\n" { > + exp_continue > + } > + } > + > + # Check a TLS variable in thread 2. > + gdb_test "print local_var" " =3D 2" \ > + "check TLS variable in thread 2" > + > + set all_same [expr [lindex $tls_reg_vals_thr_1 0] =3D=3D [lindex > $tls_reg_vals_thr_2 0] \ > + && [lindex $tls_reg_vals_thr_1 1] =3D=3D [lindex > $tls_reg_vals_thr_2 1] \ > + && [lindex $tls_reg_vals_thr_1 2] =3D=3D [lindex > $tls_reg_vals_thr_2 2]] > + gdb_assert {!$all_same} \ > + "tls regs are different between threads" > +} > + > +# Generate a core file using the gcore command. Load it into GDB and # > +check we can still read the TLS registers. > +proc_with_prefix test_gcore_tls {} { > + > + if {![gcore_cmd_available]} { > + unsupported "gcore command not available" > + return > + } > + > + clean_restart $::testfile > + > + if {![runto_main]} { > + return -1 > + } Omit -1 > + > + gdb_test_no_output "set should_dump_core_p=3D0" > + > + gdb_breakpoint crash_func > + gdb_continue_to_breakpoint "stop at crash_func" > + > + set corefile [standard_output_file ${::testfile}.gcore] > + if {![gdb_gcore_cmd $corefile "dump core"]} { > + return > + } > + > + set readelf_program [gdb_find_readelf] > + set res [catch {exec $readelf_program -n $corefile} output] > + if { $res !=3D 0 } { > + unresolved "unable to run readelf to check for TLS notes" > + return > + } > + set lines [split $output \n] > + set tls_count 0 > + foreach line $lines { > + if {[regexp "^\\s+LINUX\\s+$::hex\\s+NT_386_TLS" $line]} { > + incr tls_count > + } > + } > + gdb_assert {$tls_count =3D=3D 2} \ > + "expected number of TLS notes" > + > + load_core_and_test_tls_regs $corefile } > + > +# Generate a core file using the gcore command, but before doing so, # > +clear all the TLS related GDT entries. When the TLS GDT entries # have > +a base address and limit of zero the kernel doesn't emit the # > +NT_386_TLS note, GDB copies this behaviour. > +proc_with_prefix test_gcore_no_tls {} { > + > + if {![gcore_cmd_available]} { > + unsupported "gcore command not available" > + return > + } > + > + clean_restart $::testfile > + > + if {![runto_main]} { > + return -1 > + } > + > + gdb_test_no_output "set should_dump_core_p=3D0" > + > + gdb_breakpoint crash_func > + gdb_continue_to_breakpoint "stop at crash_func" > + > + # Clear the TLS registers in each thread. > + foreach_with_prefix thr { 1 2 } { > + gdb_test "thread $thr" ".*" \ > + "switch thread to clear tls regs" > + gdb_test_no_output "set \$i386_tls_gdt_0 =3D { 0x0, 0x0, 0x0, 0x28 }" > + gdb_test_no_output "set \$i386_tls_gdt_1 =3D { 0x0, 0x0, 0x0, 0x28 }" > + gdb_test_no_output "set \$i386_tls_gdt_2 =3D { 0x0, 0x0, 0x0, 0x28 }" > + } > + > + set corefile [standard_output_file ${::testfile}.gcore] > + if {![gdb_gcore_cmd $corefile "dump core"]} { > + return > + } > + > + # Look in the core file for NT_386_TLS entries. There should be > + # none. > + set readelf_program [gdb_find_readelf] > + set res [catch {exec $readelf_program -n $corefile} output] > + if { $res !=3D 0 } { > + unresolved "unable to run readelf to check for TLS notes" > + return > + } > + set lines [split $output \n] > + set tls_count 0 > + foreach line $lines { > + if {[regexp "^\\s+LINUX\\s+$::hex\\s+NT_386_TLS" $line]} { > + incr tls_count > + } > + } > + gdb_assert {$tls_count =3D=3D 0} \ > + "expected number of TLS notes" > + > + # Restart GDB and load the core file. As there are no NT_386_TLS > + # entries the TLS registers should show as unavailable. > + clean_restart $::testfile > + > + gdb_core_cmd $corefile "load corefile" > + > + gdb_test "info threads" \ > + [multi_line \ > + "\\*\\s+1\\s+Thread \[^\r\n\]+" \ > + "\\s+2\\s+Thread \[^\r\n\]+"] \ > + "check for two threads" > + > + foreach_with_prefix thr { 1 2 } { > + set unavailable_tls_count 0 > + set valid_tls_count 0 > + gdb_test "thread $thr" ".*" \ > + "switch thread to check TLS register status" > + gdb_test_multiple "info registers system" "check TLS reg values" { > + -re "^info registers system\r\n" { > + exp_continue > + } > + -re "^i386_tls_gdt_\\d \\{, , > , \\}\r\n" { > + incr unavailable_tls_count > + exp_continue > + } > + -re "^i386_tls_gdt_\\d \[^\r\n\]+\r\n" { > + incr valid_tls_count > + exp_continue > + } > + > + -re "^$::gdb_prompt $" { > + gdb_assert {$valid_tls_count =3D=3D 0 && \ > + $unavailable_tls_count =3D=3D 3} \ > + $gdb_test_name > + } > + -re "^\[^\r\n\]+\r\n" { > + exp_continue > + } > + } > + > + # Check a TLS variable in this thread. > + gdb_test "print local_var" " =3D $thr" \ > + "check TLS variable in thread $thr" > + } > +} > + > +# Generate a native core file. Load it into GDB and check the TLS # > +registers can be read. > +proc_with_prefix test_native_core {} { > + set corefile [core_find $::binfile] > + > + load_core_and_test_tls_regs $corefile } > + > +# Run the tests. > +test_tls_reg_availability > +test_gcore_tls > +test_gcore_no_tls > +test_native_core In case the corefile is not found (which is a common setup issue) we'll see= : ~~~ (gdb) core ^M No core file now.^M (gdb) FAIL: gdb.arch/i386-linux-tls-regs.exp: test_native_core: load corefi= le info threads^M No threads.^M (gdb) FAIL: gdb.arch/i386-linux-tls-regs.exp: test_native_core: check for t= wo threads info registers system^M The program has no registers now.^M (gdb) FAIL: gdb.arch/i386-linux-tls-regs.exp: test_native_core: check for T= LS regs thread 1 print local_var^M Cannot read `local_var' without registers^M (gdb) FAIL: gdb.arch/i386-linux-tls-regs.exp: test_native_core: check TLS v= ariable in thread 1 thread 2^M Unknown thread 2.^M (gdb) PASS: gdb.arch/i386-linux-tls-regs.exp: test_native_core: thread 2 info registers system^M The program has no registers now.^M (gdb) FAIL: gdb.arch/i386-linux-tls-regs.exp: test_native_core: check for T= LS regs thread 2 print local_var^M Cannot read `local_var' without registers^M (gdb) FAIL: gdb.arch/i386-linux-tls-regs.exp: test_native_core: check TLS v= ariable in thread 2 ERROR: tcl error sourcing /tmp/gdb.arch/i386-linux-tls-regs.exp. ERROR: missing operand at _@_ in expression " _@_=3D=3D && =3D=3D && =3D=3D " (parsing expression " =3D=3D && =3D=3D && =3D=3D ") invoked from within "expr [lindex $tls_reg_vals_thr_1 0] =3D=3D [lindex $tls_reg_vals_thr_2 0] = && [lindex $tls_reg_vals_thr_1 1] =3D=3D [lindex $tls_reg_vals_thr_2 1] &= & [lindex..." (procedure "load_core_and_test_tls_regs" line 56) invoked from within "load_core_and_test_tls_regs $corefile" ("uplevel" body line 4) invoked from within "uplevel 1 $body" invoked from within "with_test_prefix test_native_core { set corefile [core_find $::binfile] load_core_and_test_tls_regs $corefile }" (procedure "test_native_core" line 1) invoked from within "test_native_core" (file "/tmp/gdb.arch/i386-linux-tls-regs.exp" line 314) invoked from within "source /tmp/gdb.arch/i386-linux-tls-regs.exp" ~~~ I think we should better log UNTESTED and exit the test. What do you think? > diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c index > 660a906cdb6..f81622f4fea 100644 > --- a/gdb/x86-linux-nat.c > +++ b/gdb/x86-linux-nat.c > @@ -254,6 +254,73 @@ x86_linux_store_ssp (const regcache *regcache, > const int tid) > perror_with_name (_("Failed to write pl3_ssp register")); } >=20 > +/* Copy from BUFFER into REGCACHE, supplying the tls gdt entry registers= . > + Use REGNUM to decide exactly which registers are copied. */ > + > +static void > +i386_supply_tls_regs (struct regcache *regcache, int regnum, > + gdb::array_view buffer) { > + gdb_assert (buffer.size () =3D=3D 3); > + > + for (int i =3D 0; i < 3; ++i) > + { > + if (regnum =3D=3D -1 || regnum =3D=3D I386_LINUX_TLS_GDT_0 + i) > + regcache->raw_supply (I386_LINUX_TLS_GDT_0 + i, > + buffer.slice (i, 1).data ()); > + } > +} > + > +/* Copy from REGCACHE into BUFFER, collecting the tls gdt entry > + registers. USE REGNUM to decide which registers are copied. */ > + > +static void > +i386_collect_tls_regs (struct regcache *regcache, int regnum, > + gdb::array_view buffer) { > + gdb_assert (buffer.size () =3D=3D 3); > + > + for (int i =3D 0; i < 3; ++i) > + { > + if (regnum =3D=3D -1 || regnum =3D=3D I386_LINUX_TLS_GDT_0 + i) > + regcache->raw_collect (I386_LINUX_TLS_GDT_0 + i, > + buffer.slice (i, 1).data ()); > + } > +} > + > +/* See x86-linux-nat.h. */ > + > +void > +i386_fetch_tls_regs (struct regcache *regcache, int tid, int regnum) { > + struct user_desc tls_ud[3]; > + if (!i386_ptrace_get_tls_data (tid, tls_ud)) > + perror_with_name (_("Couldn't get TLS area data")); > + > + i386_supply_tls_regs (regcache, regnum, tls_ud); } > + > +/* See x86-linux-nat.h. */ > + > +void > +i386_store_tls_regs (struct regcache *regcache, int tid, int regnum) { > + /* Read current values in to TLS_UD. */ > + struct user_desc tls_ud[3]; > + if (!i386_ptrace_get_tls_data (tid, tls_ud)) > + perror_with_name (_("Couldn't get TLS area data")); > + > + /* Write new values from regcache into TLS_UD. Overwriting the > + current values. */ > + i386_collect_tls_regs (regcache, regnum, tls_ud); > + > + /* Write the new values back to the kernel. */ > + if (!i386_ptrace_set_tls_data (tid, tls_ud)) > + perror_with_name (_("Couldn't write TLS area data")); } > + > + >=20 >=20 > + > INIT_GDB_FILE (x86_linux_nat) > { > /* Initialize the debug register function vectors. */ diff --git a/gd= b/x86- > linux-nat.h b/gdb/x86-linux-nat.h index c4556532226..327ee9434b0 > 100644 > --- a/gdb/x86-linux-nat.h > +++ b/gdb/x86-linux-nat.h > @@ -25,6 +25,7 @@ > #include "gdbsupport/x86-xstate.h" > #include "x86-nat.h" > #include "nat/x86-linux.h" > +#include "i386-linux-tdep.h" >=20 > struct x86_linux_nat_target : public x86_nat_target { > @@ -103,4 +104,20 @@ extern void x86_linux_fetch_ssp (regcache > *regcache, const int tid); >=20 > extern void x86_linux_store_ssp (const regcache *regcache, const int tid= ); >=20 > +/* Fetch the tls related registers for thread TID from the kernel and pl= ace > + them into REGCACHE. If REGNUM is -1 then all 3 tls registers are > + fetched, otherwise only the register matching REGNUM is fetched. A t= ls > + register number is one for which i386_is_tls_regnum_p returns true. > +*/ > + > +extern void i386_fetch_tls_regs (struct regcache *regcache, int tid, > + int regnum); > + > +/* Store the tls related registers for thread TID from REGCACHE back in = to > + the kernel. If REGNUM is -1 then all 3 tls registers are stored, > + otherwise only the register matching REGNUM is stored. A tls registe= r > + number is one for which i386_is_tls_regnum_p returns true. */ > + > +extern void i386_store_tls_regs (struct regcache *regcache, int tid, > + int regnum); > + > #endif /* GDB_X86_LINUX_NAT_H */ > diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc inde= x > 44257d5d1ce..28edd9d8086 100644 > --- a/gdbserver/linux-x86-low.cc > +++ b/gdbserver/linux-x86-low.cc > @@ -53,6 +53,8 @@ > #include "nat/x86-linux-dregs.h" > #include "nat/x86-linux-tdesc.h" >=20 > +#include > + > #ifdef __x86_64__ > static target_desc_up tdesc_amd64_linux_no_xml; #endif @@ -132,6 > +134,10 @@ public: >=20 > int get_ipa_tdesc_idx () override; >=20 > + /* Override these to provide access to i386 TLS state. */ void > + fetch_registers (regcache *regcache, int regno) override; void > + store_registers (regcache *regcache, int regno) override; > + > protected: >=20 > void low_arch_setup () override; > @@ -573,6 +579,99 @@ static struct regset_info x86_regsets[] =3D > NULL_REGSET > }; >=20 > +/* Fetch TLS area data from the kernel and copy it into REGCACHE. REGNO > + indicates which TLS area register is wanted, or -1 for all of them. > + This function returns true if the data was fetched and stored to > + REGCACHE successfully, otherwise, it returns false. */ > + > +static bool > +fetch_tls_area_register (regcache *regcache, int regno) { > + int tid =3D current_thread->id.lwp (); > + > + /* Fetch all the TLS area data from the kernel. */ struct user_desc > + tls_ud[3]; if (!i386_ptrace_get_tls_data (tid, tls_ud)) > + return false; > + > + /* Now copy the values from TLS_UD back into the register cache. */ > + int tls_regno[3] =3D { > + find_regno (regcache->tdesc, "i386_tls_gdt_0"), > + find_regno (regcache->tdesc, "i386_tls_gdt_1"), > + find_regno (regcache->tdesc, "i386_tls_gdt_2") }; > + > + for (int i =3D 0; i < std::size (tls_regno); ++i) > + supply_register (regcache, tls_regno[i], &tls_ud[i]); > + > + return true; > +} > + > +/* See class declaration above. */ > + > +void > +x86_target::fetch_registers (regcache *regcache, int regno) { > + linux_process_target::fetch_registers (regcache, regno); > + > +#ifdef __x86_64__ > + if (!is_64bit_tdesc (current_thread)) #endif > + { > + fetch_tls_area_register (regcache, regno); fetch_tls_area_register returns true or false, shouldn't we look at the fun= ction return value? > + } > +} > + > +/* Copy TLS area data from REGCACHE back to the kernel. REGNO > indicates > + which TLS area register should be copied, or -1 for all of them. Thi= s > + function returns true if the data was stored successfully, otherwise, > + it returns false. */ > + > +static bool > +store_tls_area_registers (regcache *regcache, int regno) { > + int tid =3D current_thread->id.lwp (); > + > + /* Read current TLS area data from the kernel into TLS_UD. We then > + overwrite this with values from REGCACHE, and finally, copy the > + updated values back to the kernel. */ struct user_desc > + tls_ud[3]; if (!i386_ptrace_get_tls_data (tid, tls_ud)) > + return false; > + > + int tls_regno[] =3D { > + find_regno (regcache->tdesc, "i386_tls_gdt_0"), > + find_regno (regcache->tdesc, "i386_tls_gdt_1"), > + find_regno (regcache->tdesc, "i386_tls_gdt_2") }; > + > + /* Now copy data from REGCACHE over the top of the values written > + into TLS_UD. */ > + for (int i =3D 0; i < std::size (tls_regno); ++i) > + collect_register (regcache, tls_regno[i], &tls_ud[i]); > + > + /* And write the contents of TLS_UD back to the kernel. */ if > + (!i386_ptrace_set_tls_data (tid, tls_ud)) > + return false; > + > + return true; > +} > + > +/* See class declaration above. */ > + > +void > +x86_target::store_registers (regcache *regcache, int regno) { > + linux_process_target::store_registers (regcache, regno); > + > +#ifdef __x86_64__ > + if (!is_64bit_tdesc (current_thread)) #endif > + { > + store_tls_area_registers (regcache, regno); Same comment here for the return value. > + } > +} > + > bool > x86_target::low_supports_breakpoints () { >=20 > base-commit: 20a08d98518c0587810eb9e24aa22e7c6d56fd17 > -- > 2.47.1 >=20 Christina --===============0038220577384248253== Content-Type: multipart/alternative; boundary="===============6491299795692150501==" MIME-Version: 1.0 Content-Disposition: inline --===============6491299795692150501== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Intel Deutschland GmbH Registered Address: Dornacher Stra=C3=9Fe 1, 85622 Feldkirchen, Germany Tel: +49 89 991 430, www.intel.de Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell Chairperson of the Supervisory Board: Nicole Lau Registered Seat: Munich Commercial Register: Amtsgericht M=C3=BCnchen HRB 186928 --===============6491299795692150501== Content-Type: text/html; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable

Intel Deutschland GmbH

Registered Ad= dress: Dornacher Stra=C3=9Fe 1, 85622 Feldkirchen, Germany
Tel: +49 89 = 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneide= rman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole La= u
Registered Seat: Munich
Commercial Register: Amtsgericht M=C3=BCn= chen HRB 186928

--===============6491299795692150501==-- --===============0038220577384248253==--