From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 93378 invoked by alias); 22 Nov 2017 19:31:25 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 93365 invoked by uid 89); 22 Nov 2017 19:31:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-23.3 required=5.0 tests=AWL,BAYES_00,DIET_1,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT,KB_WAM_FROM_NAME_SINGLEWORD,SPF_PASS autolearn=ham version=3.3.2 spammy=benson, Benson X-HELO: sessmg22.ericsson.net Received: from sessmg22.ericsson.net (HELO sessmg22.ericsson.net) (193.180.251.58) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 22 Nov 2017 19:31:20 +0000 Received: from ESESSHC001.ericsson.se (Unknown_Domain [153.88.183.21]) by sessmg22.ericsson.net (Symantec Mail Security) with SMTP id A4.A8.19528.580D51A5; Wed, 22 Nov 2017 20:31:17 +0100 (CET) Received: from EUR01-DB5-obe.outbound.protection.outlook.com (153.88.183.145) by oa.msg.ericsson.com (153.88.183.21) with Microsoft SMTP Server (TLS) id 14.3.352.0; Wed, 22 Nov 2017 20:31:12 +0100 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=simon.marchi@ericsson.com; Received: from [100.94.230.86] (129.192.64.65) by AMSPR07MB312.eurprd07.prod.outlook.com (2a01:111:e400:802f::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.260.2; Wed, 22 Nov 2017 19:31:08 +0000 Subject: Re: [PATCH] linux: Add maintenance commands to test libthread_db To: Gary Benson , References: <1511361761-1333-1-git-send-email-gbenson@redhat.com> From: Simon Marchi Message-ID: Date: Wed, 22 Nov 2017 19:31:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: <1511361761-1333-1-git-send-email-gbenson@redhat.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-ClientProxiedBy: MWHPR14CA0066.namprd14.prod.outlook.com (2603:10b6:300:81::28) To AMSPR07MB312.eurprd07.prod.outlook.com (2a01:111:e400:802f::24) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a0d161e3-f59f-42a7-2ab2-08d531df95a6 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(5600022)(4604075)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603258);SRVR:AMSPR07MB312; X-Microsoft-Exchange-Diagnostics: 1;AMSPR07MB312;3:Nf7dbTuGcSxdTPTCnHtAOqFokN33lneBzo53zEn9k712qvyoMZp0+8AomFF1B7HEggE4cOAynpRoF8mosqWVUXKCb7+qPe5AZbGJLoDZFZqVo2K2Q3tAjnAUb0FbXFdrkJhkEChPQLSNFS629Ycy9Qj65WGHXwUtjb/wdRJVq251eMSFoqjrsrW/OmXwjzYkenAY238T1WwZ9xNFFhZ78BkNYpzpw6RXJMoN7wL0sEyPT1pB1nWCo0wl78bkdyHr;25:hA0nMr/gtlL2LoKEfuxFDoE7Wi5zJ/GEmkB8gVDiUNe5/82sjiUCgbgaxKMpm0eFSdR3ozhP8SDThwBL1m3DaVGcSwWoPLv+YLeSyAcEVV3001bcoDwiVGCPt5+GnpDvu0qKu/HUuOL3i5vXCfNrjMyF31XxuVNPFvCSvca/vFOZzfh9n9j15ijqZKU3Wq1vs1FtRT7V1AOf3JMiZzVhkd01/SnLmRnoFo3GnOrtPnaBiQtys/uH3v3X6cyu+DjFX5OtS9j/KU6ytVSLHK875ySSddJ9kRpJ8zi0rbGaUcqn08CLf5osWcvarQ/Nnvcsz3cAG6o3ysg37pLZBSnwcM1hQ3u2tM0EMt2mM3au+sE=;31:04yUfD37xr7wLpg5fTxsIE78Bvzzl+65xq+X8IAwftQWmVFO5FQdPg6NhO30R7bZ9PjwRCKtOGFwZHim00CV35XllQ0qyLrPmqXaQbEU0DR0E7sK6tWOS3vXdqED/CQYVN8te8AvIO567W7WepdoKnspGVElcdf99rmtd6KehiSGKVDztcVR1goeIYmE3itIqVZM+IhBcegck5mUOPsNyug5oMk1wFyXKtsEH/qhTBs= X-MS-TrafficTypeDiagnostic: AMSPR07MB312: X-Microsoft-Exchange-Diagnostics: 1;AMSPR07MB312;20:8Bty3OOuQaluVY1LMgmPRJQfNxkr6M6dccf0+XiHckyIof9qkDRlZcoh+Q8lIqPUXNjEgsSNP0CYAJGHSsXijAj0xlk7TeUsn67obBPa9nkG+d5504W7f8mYbbxA+WJuY28KZpf/tp7tkaO1Bo0FEGuZ4yVV9Z9t+xrIEcoBBYZVlgpdhAiXal/5w7SRKnKtMIHz9f9TFIvOnE3kCj/hZxcZ9QbzmvryglvJYqwgze/Rrk+6JEYKtAnvqASSMOP3N5DIqSqA2p9IMAshNa5TOXDKuxob8fYQydyuEzuvBTrk6sQczU9eHEBf2bj5wArR0THsFNGJjnR6Q05Ou4hFbx1Ci5+7FWJRpzvuWNI8DURpU9284Q962yP55hZ+Io861ufomu8UAevMp8OFo1FrqiR7/pF9ZCsIvwsVjGA2k2N0eH4eTIxUm69TMASP7320JT167yqo8x73IsGKomZU9s/7kTNKisQ8Wrxt4jnqb+lD09SsbLTiFnyE6T4bSNod;4:fGlMHF8XoaVJEeXfrkXxUZ3kmekA6aEg983bq5nj3QWF6jlsEQQccdJ9c25aWZLJ/nBPo/kgwvRpa0omvhwtaTqmon5o+QCSggmNEZTlA3VfXiaiL2+Aos+KSuHfnyaG9JtcgEQG3ieLX25PotOtQfmkz/jUI58zl11aHwn83sSNVpNdMIox7nFO85MwOwWyZfwRVd9ifhoxoz/f2OR0PVJfeCpkEQgniYuM675LUIPNJZYQ3E+r6MJuC4bIfvfhvkCQw2alIfV1vLn/hQ2p6EQhSCDXd+tceXAft30+ZuuO0ViNrzFST0Ve6houV1fUw2Gj/omHwWEz5LwgiVXgaq1J3iZhgSpXu+pzYWeUeAhMDO90ofBIcHLKne4VmOAf X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(22074186197030)(192374486261705); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(5005006)(8121501046)(100000703101)(100105400095)(10201501046)(93006095)(93001095)(3002001)(3231022)(6041248)(20161123558100)(20161123562025)(20161123560025)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123564025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:AMSPR07MB312;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:AMSPR07MB312; X-Forefront-PRVS: 0499DAF22A X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6009001)(6049001)(346002)(376002)(54534003)(24454002)(199003)(377424004)(189002)(966005)(316002)(81156014)(58126008)(6306002)(53936002)(8936002)(64126003)(478600001)(86362001)(105586002)(49976008)(83506002)(16576012)(6666003)(3846002)(2486003)(65806001)(2950100002)(6116002)(5890100001)(54356999)(229853002)(65826007)(76176999)(31696002)(2906002)(6486002)(50986999)(47776003)(25786009)(5660300001)(7736002)(230700001)(31686004)(97736004)(81166006)(65956001)(4001150100001)(53546010)(6246003)(16526018)(8676002)(36756003)(33646002)(101416001)(68736007)(305945005)(52146003)(106356001)(50466002)(189998001)(23676004)(66066001)(78286006)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:AMSPR07MB312;H:[100.94.230.86];FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; Received-SPF: None (protection.outlook.com: ericsson.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtBTVNQUjA3TUIzMTI7MjM6VGF1aHZZbFNBWTlVUTF6cDNtV3o4N1ZmZ203?= =?utf-8?B?MHdMdWVhZjBzRi93STZvK1liNUJLOWdVSEFZUkpZV2grMitaZU5nbXc5WGor?= =?utf-8?B?MTVocVZrUXpzVWw0bzBPcFFodDVsQWM0bXdESytwYjVNU04vUHVCd3M1aWNI?= =?utf-8?B?NDdjZ3FQL1NyRHo4eWFDVjlZSWZ0S2JyNXdxbDFDc2lRRzlkdFlmWEVHZzg1?= =?utf-8?B?MWJ0aGxMZUhJK2N1MUFYUEV4b3c2eVhuSll5WmQ0NWFkMEs0Skc5S2tFdWVR?= =?utf-8?B?a0UrSVBldXpnc1N0ZTFQYTFvaHR1dm04MVFZM29xLzl0WGJaMk5aWWF4WUk4?= =?utf-8?B?cUJqRTBaUTA4aUQzTnd2YnQzQkRzbGc2OFZUbG85WFFxcVZQbTJpd09wQ2Z3?= =?utf-8?B?dkoxa3ZuWFpWT2ZNVnBVTndwM25MVVJTc3NCSHh3SEVMRUVyZ3Y4c3M5ZERx?= =?utf-8?B?OGdwVW04NWUxK3I5d0lzOGJLeTBwWXQrWWVpbjJpYzU5VmxmNkQ0MU9UUmM0?= =?utf-8?B?Um5NY2RCNmFjVjFYZmRKVDkyUExNMHYwcVI0bVdzSFRaTitweVZPUkxDZGN6?= =?utf-8?B?UHcxQVZvTUswYVJ6ZXk1ejZjYlg5aENDYjZGSUZsRmZFRVpZUGJLMEI3SWp6?= =?utf-8?B?dTlvTDhHT1BKZDFvRjlRYmZQa2t2TFJpZlZFTElLSTdBczgzc2NpbFhPb1Mw?= =?utf-8?B?RUVRSEhZN2VqL240V1RNenBFKzdlR1VoVU9oWXN6RHZuZEt6cUtrb3htZEJa?= =?utf-8?B?Mkg3UlExZDU2L2w2NDIybHdJZnorRXdGaDJPQXdHa0dRQ3lzVXBLSHA1Z3Rn?= =?utf-8?B?KzhpSHAvc256cDZpbVFuWlpacTBQMVNZVU5uSGNSS3VybTBlL3dNZm9JVzZP?= =?utf-8?B?dTFOeXpvSFBUdXI4aXF4YmpKb29aZWVTZmZ6Y3BOU0JpQUVjeng4SllyYmFv?= =?utf-8?B?VVpqdFFMejlGSmZDOEkrY1BLdFlSYldDaS9EUXpSOVFtQXBCRVdnVGY2ZTJL?= =?utf-8?B?di9rSEtOcGt5NU1Ba2pXOGV3elZ1TEUwbVpURkJ0RFRRQ3FyRW5idzNDVDhN?= =?utf-8?B?VXRxOWFZUHMzeGVMV0RMa3E2TkZFdXJ2RjVsRCtaYUR0cm9jbnQ0bVNydTRy?= =?utf-8?B?cWl4UGdvbHVQU3NobXpBcEE2Ym1PeTNtSlZBcUdNSUdGRGRSZUZFVlZuMnY1?= =?utf-8?B?T1Q0cng4K2JMMmV2c2QrRTNuL0RGWEVaTjY3WTU4Ti9CcEppd3ExdndXUGt3?= =?utf-8?B?Y1NsMVM3aWJIQlhyTDEwanFwR2xlNDdiRGtxT3JrTEIyU01uWnFtQUpXYXg4?= =?utf-8?B?dngyYk9oVmZzTnZzSGlMcVZJcWdUZDJWWGJBZXhnV2pJb01hbzQzcmpLU1Ja?= =?utf-8?B?bm5TL0hxS2lGRlM2U0F1S2U0VXVHc1RuSnIyNkVQV09MNWwxYkNKc0d5SHFt?= =?utf-8?B?M1RCcmMyVVFadEtGczNqa2dSVjhLcEE5bnZsYld3TEJzUlNTdVEyUUtzdG1W?= =?utf-8?B?bXN4QTNRbDYrQUJDMGtuUmFmVy9YbFlYTVo5dDk5TUVvODcrM3VQMEN5eFN1?= =?utf-8?B?THpMbmQrUEJOK0xZUlpMa3drQ0JBdnZVbDlWTXBTR3B5VktkWjFJeURvTFZT?= =?utf-8?B?RW9FR1B2Qk1nZ2JKYldLdjNSSlZIUXdsT0psOTMwSlZJczZVUlMwdDFieDZy?= =?utf-8?B?dG5NeUJSaG1hUHd2bWFTc1ZibXVON2VkcE1EMmJQWUlaK2lrYWlqYkg3S1RP?= =?utf-8?B?WVZEOXBubFh4clBPdTBzM3Jsa3Q3NFNLZjVYajZwVWZ6SmRTVXVEYjVabkJy?= =?utf-8?B?aFlRQmo2Q0o1eE8zTTNIc1dQSjI4NHMrRm5wT1FkV2JzdnkxSnpLelBONW50?= =?utf-8?B?emtQUlo1cnJCTGo3K0lJZkpaeXc0NzlTa1RIMzV0Um5hQnlOblN3TTQ2OG5G?= =?utf-8?B?VWZ2TDRDakg0Y05mcm43ejNOekk3bTN3ZVFhZDhSNldWeVFkTitXMVphT09u?= =?utf-8?B?N2lkNFVtZ0lsOGdCM3VTQ2FaUE14MDdEdUl3PT0=?= X-Microsoft-Exchange-Diagnostics: 1;AMSPR07MB312;6:VHyusMCTDwtM4zzQnQNuEHXR+OiSeZ5YzFmeGJqbdhf0UiaIAY7K8noB/D07wGf8880j06O0migS5cANpv+zrkUYAZ9EYImMtoStVyRCBFbVW82ODPODYeA1JawewK+rsouBUgKbGPv3leZ8/eS1skS6KbbnyMHJQ0dWVvuI3USc/oqdkuSVIuJ55XEjLHRs+/aJP4Hvd7T0q9ORXY7Dz8fMdtMfzhbBTI/C4eqaYn9CdvhJcpKpvMTeokOmrktgEYJQ5UF9iR6KhTWFy4gWNv+pj5i+tmVO319ptqdftzgbxjDcvRVnCpB7vSGkHvk52WDUdGqVFwXURw9ohSFAqHHb0756fRR50Kkqur9ya6U=;5:9eN69BePqpimgm5I56YomgGPTyIvCHmBuV2y5PefF+RTV2eXGN1rJK4CnuX/kk1wkKXUUkOzYEJSDtyFrd8ywC3UELmgTMZCJIGbfq4xe8bQzdLIHDApGkkV+HKdDgioAJQ4dWdebHhdPKi3aDmwp0wIbfzVN0DNPA1Kw+5gsGM=;24:NKyNpTO3ikgzn525ByDnFLkNMC2DSnhPQUEy4FkqfQXrlVMUbKk1FKU//C/YZv7Ryzd7VflbgmpR8GaIC6Nj3gsiSDG8g1KkYwiKWGNcMWs=;7:cOpMsIuvTW0LUwZwoNJzJZ9/5gF8Oc5NDaRtE5sM5AdGmpK/tSf+Y3Z5o/TA4QAG7nCXO5sQYxtN6KfnRdwB0f4PbdZFxJ7lYtThDu4Q7Y3bsDiQ0hCNsfLutRvEmOoClIynxfPD/YZLMvNrcie3tQgU5jHjSVJV4N4MHqbuKTYIzMVU0rjzkdTr/2wCcbTA6XeV+t8Csp4/Zq7SWEFBtHhYhuXjsqUwpCFmzZSG878BcU6M4YEWt9btqhKSFv7j SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2017 19:31:08.9393 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: a0d161e3-f59f-42a7-2ab2-08d531df95a6 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-Transport-CrossTenantHeadersStamped: AMSPR07MB312 X-OriginatorOrg: ericsson.com X-IsSubscribed: yes X-SW-Source: 2017-11/txt/msg00509.txt.bz2 On 2017-11-22 09:42 AM, Gary Benson wrote: > This commit adds two new commands which may be used to test thread > debugging libraries used by GDB: > > * "maint check libthread-db" tests the thread debugging library GDB > is using for the current inferior. > > * "maint set/show check-libthread-db" selects whether libthread_db > tests should be run automatically as libthread_db is auto-loaded. > The default is to not run tests automatically. > > The test itself is a basic integrity check exercising all libthread_db > functions used by GDB on GNU/Linux systems. By extension this also > exercises the proc_service functions provided by GDB that libthread_db > uses. > > This functionality is useful for NPTL developers and libthread_db > developers. It could also prove useful investigating bugs reported > against GDB where the thread debugging library or GDB's proc_service > layer is suspect. > > Built and regtested on RHEL 7.4 x86_64. > > Ok to commit? > > Thanks, > Gary Hi Gary, You have much more experience than I do in this domain, so I'll trust you if you say it's useful :). I noted a few comments below, nothing major. I would be fine with the patch being committed with those fixed, but maybe give the others a week or so if they want to add comment (including Eli for the doc). If you don't hear anything more after a week, please go ahead and push. > > -- > gdb/ChangeLog: > > * linux-thread-db.c (valprint.h): New include. > (struct check_thread_db_info): New structure. > (check_thread_db_on_load, tdb_testinfo): New static globals. > (check_thread_db, check_thread_db_callback): New functions. > (try_thread_db_load_1): Run integrity checks if requested. > (maintenance_check_libthread_db): New function. > (_initialize_thread_db): Register "maint check libthread-db" > and "maint set/show check-libthread-db". > > gdb/doc/ChangeLog: > > * gdb.texinfo (Maintenance Commands): Document "maint check > libthread-db" and "maint set/show check-libthread-db". > > gdb/testsuite/ChangeLog: > > * gdb.threads/check-libthread-db.exp: New file. > * gdb.threads/check-libthread-db.c: Likewise. > --- > gdb/ChangeLog | 11 + > gdb/doc/ChangeLog | 5 + > gdb/doc/gdb.texinfo | 13 ++ > gdb/linux-thread-db.c | 257 +++++++++++++++++++++++ > gdb/testsuite/ChangeLog | 5 + > gdb/testsuite/gdb.threads/check-libthread-db.c | 66 ++++++ > gdb/testsuite/gdb.threads/check-libthread-db.exp | 114 ++++++++++ > 7 files changed, 471 insertions(+) > create mode 100644 gdb/testsuite/gdb.threads/check-libthread-db.c > create mode 100644 gdb/testsuite/gdb.threads/check-libthread-db.exp > > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index 29d4789..4d7a7b1 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -34981,6 +34981,11 @@ modify XML target descriptions. > Check that the target descriptions dynamically created by @value{GDBN} > equal the descriptions created from XML files found in @var{dir}. > > +@kindex maint check libthread-db > +@item maint check libthread-db > +Run integrity checks on the current inferior's thread debugging > +library. > + > @kindex maint print dummy-frames > @item maint print dummy-frames > Prints the contents of @value{GDBN}'s internal dummy-frame stack. > @@ -35288,6 +35293,14 @@ number of blocks in the blockvector > @end enumerate > @end table > > +@kindex maint set check-libthread-db > +@kindex maint show check-libthread-db > +@item maint set check-libthread-db [on|off] > +@itemx maint show check-libthread-db > +Control whether @value{GDBN} should run integrity checks on inferior > +specific thread debugging libraries as they are loaded. The default > +is not to perform such checks. > + > @kindex maint space > @cindex memory used by commands > @item maint space @var{value} > diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c > index ea032fc..d1fdb33 100644 > --- a/gdb/linux-thread-db.c > +++ b/gdb/linux-thread-db.c > @@ -46,6 +46,7 @@ > #include > #include "nat/linux-namespaces.h" > #include > +#include "valprint.h" > > /* GNU/Linux libthread_db support. > > @@ -80,6 +81,10 @@ static char *libthread_db_search_path; > by the "set auto-load libthread-db" command. */ > static int auto_load_thread_db = 1; > > +/* Set to non-zero if load-time libthread_db tests have been enabled > + by the "maintenence set check-libthread-db" command. */ "maintenence". > +static int check_thread_db_on_load = 0; > + > /* "show" command for the auto_load_thread_db configuration variable. */ > > static void > @@ -493,6 +498,216 @@ dladdr_to_soname (const void *addr) > return NULL; > } > > +/* State for check_thread_db_callback. */ > + > +struct check_thread_db_info > +{ > + /* The libthread_db under test. */ > + struct thread_db_info *info; > + > + /* True if progress should be logged. */ > + bool log_progress; > + > + /* True if the callback was called. */ > + bool threads_seen; > +}; > + > +static struct check_thread_db_info *tdb_testinfo; > > + > +/* Callback for check_thread_db. */ > + > +static int > +check_thread_db_callback (const td_thrhandle_t *th, void *arg) > +{ > + gdb_assert (tdb_testinfo != NULL); > + tdb_testinfo->threads_seen = true; > + > +#define LOG(fmt, args...) \ > + do \ > + { \ > + if (tdb_testinfo->log_progress) \ > + { \ > + debug_printf (fmt, ## args); \ > + gdb_flush (gdb_stdlog); \ > + } \ > + } \ > + while (0) > + > +#define __CHECK(expr, args...) \ > + do \ > + { \ > + if (!(expr)) \ > + { \ > + LOG (" ... FAIL!\n"); \ > + error (args); \ > + } \ > + } \ > + while (0) > + > +#define CHECK(expr) \ > + __CHECK (expr, "(%s) == false", #expr) > + > +#define CHECK_CALL(func, args...) \ > + do \ > + { \ > + td_err_e __err = tdb_testinfo->info->func ## _p (args); \ > + \ > + __CHECK (__err == TD_OK, _("%s failed: %s"), #func, \ > + thread_db_err_str (__err)); \ > + } \ > + while (0) > + > + LOG (" Got thread"); > + > + /* Check td_ta_thr_iter passed consistent arguments. */ > + CHECK (th != NULL); > + CHECK (arg == (void *) tdb_testinfo); > + CHECK (th->th_ta_p == tdb_testinfo->info->thread_agent); > + > + LOG (" %s", core_addr_to_string_nz ((CORE_ADDR) th->th_unique)); > + > + /* Check td_thr_get_info. */ > + td_thrinfo_t ti; > + CHECK_CALL (td_thr_get_info, th, &ti); > + > + LOG (" => %d", ti.ti_lid); > + > + CHECK (ti.ti_ta_p == th->th_ta_p); > + CHECK (ti.ti_tid == (thread_t) th->th_unique); > + > + /* Check td_ta_map_lwp2thr. */ > + td_thrhandle_t th2; > + memset (&th2, 23, sizeof (td_thrhandle_t)); > + CHECK_CALL (td_ta_map_lwp2thr, th->th_ta_p, ti.ti_lid, &th2); > + > + LOG (" => %s", core_addr_to_string_nz ((CORE_ADDR) th2.th_unique)); > + > + CHECK (memcmp (th, &th2, sizeof (td_thrhandle_t)) == 0); > + > + /* Attempt TLS access. Assuming errno is TLS, this calls > + thread_db_get_thread_local_address, which in turn calls > + td_thr_tls_get_addr for live inferiors or td_thr_tlsbase > + for core files. This test is skipped if the thread has > + not been recorded; proceeding in that case would result > + in the test having the side-effect of noticing threads > + which seems wrong. > + > + Note that in glibc's libthread_db td_thr_tls_get_addr is > + a thin wrapper around td_thr_tlsbase; this check always > + hits the bulk of the code. > + > + Note also that we don't actually check any libthread_db > + calls are made, we just assume they were; future changes > + to how GDB accesses TLS could result in this passing > + without exercising the calls it's supposed to. */ > + ptid_t ptid = ptid_build (tdb_testinfo->info->pid, ti.ti_lid, 0); > + struct thread_info *thread_info = find_thread_ptid (ptid); > + if (thread_info != NULL && thread_info->priv != NULL) > + { > + LOG ("; errno"); > + > + scoped_restore_current_thread restore_current_thread; > + switch_to_thread (ptid); > + > + expression_up expr = parse_expression ("errno"); Without debug symbols for libc, I get this (gdb) maintenance check libthread-db Running libthread_db integrity checks: Got thread 0x7ffff7fc0700 => 7975 => 0x7ffff7fc0700; errnowarning: libthread_db integrity checks failed: 'errno' has unknown type; cast it to its declared type thanks to Pedro's no-debuginfo changes :). I think it could easily be worked around with - expression_up expr = parse_expression ("errno"); + expression_up expr = parse_expression ("(int) errno"); so that the test works even without libc debug info. With that change, I get this, which looks good: (gdb) maintenance check libthread-db Running libthread_db integrity checks: Got thread 0x7ffff7fc0700 => 8928 => 0x7ffff7fc0700; errno = 0 ... OK libthread_db integrity checks passed. > + struct value *val = evaluate_expression (expr.get ()); > + > + if (tdb_testinfo->log_progress) > + { > + struct value_print_options opts; > + > + get_user_print_options (&opts); > + LOG (" = "); > + value_print (val, gdb_stdlog, &opts); > + } > + } > + > + LOG (" ... OK\n"); > + > +#undef LOG > +#undef __CHECK > +#undef CHECK > +#undef CHECK_CALL > + > + return 0; > +} > + > +/* Run integrity checks on the dlopen()ed libthread_db described by > + INFO. Returns true on success, displays a warning and returns > + false on failure. Logs progress messages to gdb_stdlog during > + the test if LOG_PROGRESS is true. */ > + > +static bool > +check_thread_db (struct thread_db_info *info, bool log_progress) > +{ > + bool test_passed = true; > + > + if (log_progress) > + debug_printf (_("Running libthread_db integrity checks:\n")); > + > + /* GDB avoids using td_ta_thr_iter wherever possible (see comment > + in try_thread_db_load_1 below) so in order to test it we may > + have to locate it ourselves. */ > + td_ta_thr_iter_ftype *td_ta_thr_iter_p = info->td_ta_thr_iter_p; > + if (td_ta_thr_iter_p == NULL) > + { > + void *thr_iter = verbose_dlsym (info->handle, "td_ta_thr_iter"); > + if (thr_iter == NULL) > + return 0; > + > + td_ta_thr_iter_p = (td_ta_thr_iter_ftype *) thr_iter; > + } > + > + /* Set up the test state we share with the callback. */ > + gdb_assert (tdb_testinfo == NULL); > + struct check_thread_db_info tdb_testinfo_buf; > + tdb_testinfo = &tdb_testinfo_buf; > + > + memset (tdb_testinfo, 0, sizeof (struct check_thread_db_info)); > + tdb_testinfo->info = info; > + tdb_testinfo->log_progress = log_progress; Just a nit, but check_thread_db_info could use a constructor that receives these as parameters. > + > + /* td_ta_thr_iter shouldn't be used on running processes. */ > + linux_stop_and_wait_all_lwps (); > + > + TRY > + { > + td_err_e err = td_ta_thr_iter_p (info->thread_agent, > + check_thread_db_callback, > + tdb_testinfo, > + TD_THR_ANY_STATE, > + TD_THR_LOWEST_PRIORITY, > + TD_SIGNO_MASK, > + TD_THR_ANY_USER_FLAGS); > + > + if (err != TD_OK) > + error (_("td_ta_thr_iter failed: %s"), thread_db_err_str (err)); > + > + if (!tdb_testinfo->threads_seen) > + error (_("no threads seen")); > + } > + CATCH (except, RETURN_MASK_ERROR) > + { > + if (warning_pre_print) > + fputs_unfiltered (warning_pre_print, gdb_stderr); > + > + exception_fprintf (gdb_stderr, except, > + _("libthread_db integrity checks failed: ")); > + > + test_passed = false; > + } > + END_CATCH > + > + if (test_passed && log_progress) > + debug_printf (_("libthread_db integrity checks passed.\n")); > + > + tdb_testinfo = NULL; > + > + linux_unstop_all_lwps (); > + > + return test_passed; > +} > + > /* Attempt to initialize dlopen()ed libthread_db, described by INFO. > Return 1 on success. > Failure could happen if libthread_db does not have symbols we expect, > @@ -586,6 +801,13 @@ try_thread_db_load_1 (struct thread_db_info *info) > #undef TDB_DLSYM > #undef CHK > > + /* Run integrity checks if requested. */ > + if (check_thread_db_on_load) > + { > + if (!check_thread_db (info, libthread_db_debug != 0)) You can use simply "libthread_db_debug" instead of "libthread_db_debug != 0", since it's semantically a bool. > + return 0; > + } > + > if (info->td_ta_thr_iter_p == NULL) > { > struct lwp_info *lp; > @@ -1704,6 +1926,24 @@ info_auto_load_libthread_db (const char *args, int from_tty) > uiout->message (_("No auto-loaded libthread-db.\n")); > } > > +/* Implement 'maintenance check libthread-db'. */ > + > +static void > +maintenance_check_libthread_db (const char *args, int from_tty) > +{ > + int inferior_pid = ptid_get_pid (inferior_ptid); > + struct thread_db_info *info; > + > + if (inferior_pid == 0) > + error (_("No inferior running")); > + > + info = get_thread_db_info (inferior_pid); > + if (info == NULL) > + error (_("No libthread_db loaded")); > + > + check_thread_db (info, true); > +} > + > static void > init_thread_db_ops (void) > { > @@ -1780,6 +2020,23 @@ This options has security implications for untrusted inferiors."), > Usage: info auto-load libthread-db"), > auto_load_info_cmdlist_get ()); > > + add_cmd ("libthread-db", class_maintenance, > + maintenance_check_libthread_db, _("\ > +Run integrity checks on the current inferior's libthread_db."), > + &maintenancechecklist); > + > + add_setshow_boolean_cmd ("check-libthread-db", > + class_maintenance, > + &check_thread_db_on_load, _("\ > +Set whether to check libthread_db at load time."), _("\ > +Show whether to check libthread_db at load time."), _("\ > +If enabled GDB will run integrity checks on inferior specific libthread_db\n\ > +as they are loaded."), > + NULL, > + NULL, > + &maintenance_set_cmdlist, > + &maintenance_show_cmdlist); > + > /* Add ourselves to objfile event chain. */ > observer_attach_new_objfile (thread_db_new_objfile); > > diff --git a/gdb/testsuite/gdb.threads/check-libthread-db.c b/gdb/testsuite/gdb.threads/check-libthread-db.c > new file mode 100644 > index 0000000..22be229 > --- /dev/null > +++ b/gdb/testsuite/gdb.threads/check-libthread-db.c > @@ -0,0 +1,66 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2017 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 > +#include > +#include > + > +static void > +break_here (void) > +{ > +} > + > +static void * > +thread_routine (void *arg) > +{ > + errno = 42; > + > + break_here (); > + > + while (1) > + sleep (1); > + > + return NULL; > +} > + > +int > +main (int argc, char *argv) > +{ > + pthread_t the_thread; > + int err; > + > + err = pthread_create (&the_thread, NULL, thread_routine, NULL); > + if (err != 0) > + { > + fprintf (stderr, "pthread_create: %s (%d)\n", strerror (err), err); > + exit (EXIT_FAILURE); > + } > + > + errno = 23; > + > + err = pthread_join (the_thread, NULL); > + if (err != 0) > + { > + fprintf (stderr, "pthread_join: %s (%d)\n", strerror (err), err); > + exit (EXIT_FAILURE); > + } > + > + exit (EXIT_SUCCESS); > +} > diff --git a/gdb/testsuite/gdb.threads/check-libthread-db.exp b/gdb/testsuite/gdb.threads/check-libthread-db.exp > new file mode 100644 > index 0000000..3990cf3 > --- /dev/null > +++ b/gdb/testsuite/gdb.threads/check-libthread-db.exp > @@ -0,0 +1,114 @@ > +# Copyright 2017 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 test only works for native processes on Linux. > +if { ![isnative] || [is_remote host] || [target_info exists use_gdb_stub] > + || ![istarget *-linux*] } { > + continue > +} > + > +standard_testfile > + > +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ > + executable debug] != "" } { > + return -1 > +} > + > +# TEST 1: Manual check with libthread_db not loaded. > + > +clean_restart ${binfile} > + > +gdb_test "maint show check-libthread-db" \ > + "Whether to check libthread_db at load time is off." > + > +gdb_test_no_output "set stop-on-solib-events 1" > +gdb_run_cmd > +gdb_test "" \ > + ".*Stopped due to shared library event.*no libraries added or removed.*" > + > +gdb_test "maint check libthread-db" \ > + "No libthread_db loaded" \ > + "libpthread.so not loaded" > + > + > +# TEST 2: Manual check with NPTL uninitialized. > +# libthread_db should fake a single thread with th_unique == NULL. > + > +gdb_test "continue" \ > + ".*Stopped due to shared library event.*Inferior loaded .*libpthread.*" > + > +gdb_test_sequence "maint check libthread-db" \ > + "libpthread.so not initialized (manual)" { Don't use test names that end with something in parentheses, see: https://sourceware.org/gdb/wiki/GDBTestcaseCookbook#Do_not_use_.22tail_parentheses.22_on_test_messages To keep names unique, you can either just change the format of the message, or wrap the code with with_test_prefix "manual" { ... } with_test_prefix "automated" { ... } > + "\[\r\n\]+Running libthread_db integrity checks:" > + "\[\r\n\]+\[ \]+Got thread 0x0 => \[0-9\]+ => 0x0 ... OK" > + "\[\r\n\]+libthread_db integrity checks passed." > + } > + > + > +# TEST 3: Manual check with NPTL fully operational. > + > +gdb_test_no_output "set stop-on-solib-events 0" > +gdb_breakpoint break_here > +gdb_continue_to_breakpoint break_here > + > +gdb_test_sequence "maint check libthread-db" \ > + "libpthread.so fully initialized (manual)" { > + "\[\r\n\]+Running libthread_db integrity checks:" > + "\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+; errno = 23 ... OK" > + "\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+; errno = 42 ... OK" > + "\[\r\n\]+libthread_db integrity checks passed." > + } > + > + > +# TEST 4: Automated check with NPTL uninitialized. > + > +clean_restart ${binfile} > + > +gdb_test_no_output "maint set check-libthread-db 1" > +gdb_test_no_output "set debug libthread-db 1" > +gdb_breakpoint break_here > +gdb_run_cmd > + > +gdb_test_sequence "" \ > + "libpthread.so not initialized (automated)" { > + "\[\r\n\]+Running libthread_db integrity checks:" > + "\[\r\n\]+\[ \]+Got thread 0x0 => \[0-9\]+ => 0x0 ... OK" > + "\[\r\n\]+libthread_db integrity checks passed." > + "\[\r\n\]+[Thread debugging using libthread_db enabled]" > + } > + > + > +# TEST 5: Automated check with NPTL fully operational. > + > +clean_restart ${binfile} > + > +gdb_test_no_output "maint set check-libthread-db 1" > +gdb_test_no_output "set debug libthread-db 1" > + > +set test_spawn_id [spawn_wait_for_attach $binfile] > +set testpid [spawn_id_get_pid $test_spawn_id] > + > +gdb_test_sequence "attach $testpid" \ > + "libpthread.so fully initialized (automated)" { > + "\[\r\n\]+Running libthread_db integrity checks:" > + "\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+ ... OK" > + "\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+ ... OK" > + "\[\r\n\]+libthread_db integrity checks passed." > + "\[\r\n\]+[Thread debugging using libthread_db enabled]" > + } > + > + > +gdb_exit > +kill_wait_spawned_process $test_spawn_id > Thanks, Simon