From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 0CG/Fyh9WWgt1hoAWB0awg (envelope-from ) for ; Mon, 23 Jun 2025 12:13:28 -0400 Received: by simark.ca (Postfix, from userid 112) id 5BE761E11C; Mon, 23 Jun 2025 12:13:28 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-9.0 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED, RCVD_IN_VALIDITY_RPBL,RCVD_IN_VALIDITY_SAFE 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 30BC41E0C2 for ; Mon, 23 Jun 2025 12:13:26 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CF27D386B7C6 for ; Mon, 23 Jun 2025 16:13:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CF27D386B7C6 Received: from us-smtp-delivery-114.mimecast.com (us-smtp-delivery-114.mimecast.com [170.10.133.114]) by sourceware.org (Postfix) with ESMTP id 1A52C384670C for ; Mon, 23 Jun 2025 16:10:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1A52C384670C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=labware.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=labware.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1A52C384670C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.114 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750695059; cv=none; b=K6h7dSWo+RI3heTpLK3r/vUv7gGmH0jTNLUas+sTfgaYxlMWHWp54feasx7GrupIJQVxno4khlnPITg9yOlCCsJiGOio6Tz4NV87mnXUzkqEO/8QFoSkqD9pZBRqjL0//+tuDSMq2SMAx9ihWKFq4nbjf07lxTlHpgMJatHILR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1750695059; c=relaxed/simple; bh=jjDOeGq+RtYraOn8m9yq60u90szer20brMrjIPDv//A=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=APeuiB/64NoCM63Bs4m8H0Szo4yGX/bUEoMqJcruEcKKOPrBHnMVYIBF9GEikSDZJNxPsUGJ6zZRWLqKbqh3rBqKT5B2fmwzFNudFaHfrcV7QhhPRsv+5FaKwbcU/97Oh49SruZ8qfcCo1Tnfe1JmxH7RKVfhO36A0Un+Oq5nTU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1A52C384670C Received: from NAM12-BN8-obe.outbound.protection.outlook.com (mail-bn8nam12on2096.outbound.protection.outlook.com [40.107.237.96]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-662-OBscmUoPOkGKv6zZZe-yiA-1; Mon, 23 Jun 2025 12:10:57 -0400 X-MC-Unique: OBscmUoPOkGKv6zZZe-yiA-1 X-Mimecast-MFC-AGG-ID: OBscmUoPOkGKv6zZZe-yiA_1750695057 Received: from SA1PR17MB5365.namprd17.prod.outlook.com (2603:10b6:806:1d8::11) by PH0PR17MB4637.namprd17.prod.outlook.com (2603:10b6:510:81::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8857.29; Mon, 23 Jun 2025 16:10:56 +0000 Received: from SA1PR17MB5365.namprd17.prod.outlook.com ([fe80::6398:7dc0:7d88:5a4d]) by SA1PR17MB5365.namprd17.prod.outlook.com ([fe80::6398:7dc0:7d88:5a4d%5]) with mapi id 15.20.8857.026; Mon, 23 Jun 2025 16:10:55 +0000 From: Jan Vrany To: gdb-patches@sourceware.org CC: Jan Vrany , Eli Zaretskii Subject: [RFC v5 07/18] gdb/python: add gdb.Compunit Date: Mon, 23 Jun 2025 17:10:02 +0100 Message-ID: <20250623161013.650814-8-jan.vrany@labware.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250623161013.650814-1-jan.vrany@labware.com> References: <20250623161013.650814-1-jan.vrany@labware.com> X-ClientProxiedBy: LO4P265CA0070.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:2af::10) To SA1PR17MB5365.namprd17.prod.outlook.com (2603:10b6:806:1d8::11) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SA1PR17MB5365:EE_|PH0PR17MB4637:EE_ X-MS-Office365-Filtering-Correlation-Id: 0d7db9b9-952a-4bf0-1f68-08ddb27088c1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|13003099007 X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?jsjpEP3deiKyZUuTsrVnYhuMcypQ02scNriidLeYk+raqucEAtzEBK9wIAtN?= =?us-ascii?Q?zHpTwyW6jwfMeEYNbzxSS2WHeRh14sfhkQhnRCesr04uDh3fp3mC9wyvTSMM?= =?us-ascii?Q?nzB2VXb4k9LsMrAyBdk6ryhY661sPSaVvW5tidP+soLRPoP8rOLA50/RxVY4?= =?us-ascii?Q?F+2s0j7OXwYxV2DB/q42tSOqkiY24L9TaRcJbnzYUqHLSrZ6Br/EnnMCkSn3?= =?us-ascii?Q?gJw7ZQtvs7e5TxhsKoHLcGwPV2ZsyYSvK3m1s2rM8kLE3swrWBst0MvNtn4R?= =?us-ascii?Q?PhmUO6TbmALe8hSzRqo3sRIIOt1uh4rsbO9gYXnmrSLKg0bmduvnYrjJT+GQ?= =?us-ascii?Q?W9T9hsjvErh8W8EiDRT/59DdBMaUXPtHhVDfkN9h4sN7bXAEsLUg8ohhKkGW?= =?us-ascii?Q?NVbAEJSAmkHM06DFa4hHt+dWquREvVNoQyb5f8k9pHWZABopHjIh+PAlSszp?= =?us-ascii?Q?1YIoC0u6XXJVI2ZcpiXmR88SgB3Obp3gqBol51Q9nk4rtaiqTGcuAwnd5+Hy?= =?us-ascii?Q?s4W3/d5k+8W/UY1eRiiV4TamkAhLs5SMq5Qkvyxe/yM9Pe3wfSa1APdiVH1W?= =?us-ascii?Q?NEovbEXuAC3w0NYUzL0ieEOuwYB+iVw9cTWBfMq+G1S4wyIj8teWa2RKSCs/?= =?us-ascii?Q?UHCBBA3QCmbya7luWpXOAPNPIEw1LEkmlbHp1B3sKSei6rOYOsANu6wQiLn9?= =?us-ascii?Q?6EubHgeKT9Oj7XSzGoGWsFgDFT8XQT/9DJNARP3M9M/fBs9qTYp+I5Ybf5cF?= =?us-ascii?Q?u7qJNtwDV+uevtMofnIM9/os/V0qZjNdeuXPLGtSwUUksnn0S0LEKCOZNDt7?= =?us-ascii?Q?AkMR+v2nIWKvxkWQvMyVAfriCqEBp1WSHzVcyKmklHl7dkEZgbPLPSPDB14J?= =?us-ascii?Q?QbjrfDvLI7S5rfnoWpkMwuoVhDcK8I1IfjDWXX0qaPmCvKOh6ZhVbP7k4h7T?= =?us-ascii?Q?Dob8Grl2mboT+ASx0hloVbi3zpWPxUvHD7w64eNwrCoyo/+ta+rBQzamNnST?= =?us-ascii?Q?kp4/bO/2AriZOUal+EzpC8SYv2rJUZ+1pA6kRG+0qSaHWyOfa4Z90ThRd95w?= =?us-ascii?Q?dRkyVkv7ZrmVhIvqkvSg/Qj/BwKNAVHx7IExrggQnaAk1+ovwMSMvOWQNEdr?= =?us-ascii?Q?finNR3LEElNafjS0hkmuKNvK9wZlv3rgaBoHv1zaGPFhrPIp1qG8m1Wptprt?= =?us-ascii?Q?ZwGadDqIR8a3E2qGnKU2f8zho/6s+/ADx9+CwDEZznarmOXeL/sCP5BBeYpp?= =?us-ascii?Q?++Z57oAG8iP3wwAmse+dU/wduzKfxc1hCWecV5Sg4dhHh0MjU0rzrGtcLTbq?= =?us-ascii?Q?5VDrP/WeSvhpKsckIvaNoMrK6UqyT4KS5eT2d9Qve6bNwtdbIDZrJmxX0w/8?= =?us-ascii?Q?qiABnOFEqtAI1tw/pzY/pu/mh74lR/Z0R92NZ7Cpm/GivbjjxYQ3MFJ4o/+y?= =?us-ascii?Q?+ofCNIZQ8U0=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SA1PR17MB5365.namprd17.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(376014)(1800799024)(13003099007); DIR:OUT; SFP:1102 X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?IbrRnDtZOi3p8lbvpJ6FUbfbenPs9xWqm4TIsFMQBbWm9iK30qyfpHcXIsnT?= =?us-ascii?Q?PIO610RwFL/afzRrQIZdS+9O7LRI5xqt5JxB+2riYG1zV4Uef+lr8zRZrE6r?= =?us-ascii?Q?Z/CglODEXhg4QoiXHy1CckCLHAX9jNJSnfbsVM8fKbbgXNEpfhWWGtbI6Fsi?= =?us-ascii?Q?MU6oc+x6p8TsW1bjRbEcVSGHik5nsda3DcPCRXhqYqzZhliXiT7OXl1EG41u?= =?us-ascii?Q?HzpbhUhGlvpP9Bi4RcI0uWT0w+i6DfxyxVXZdYDploiEn2ODydjg0EKLqDth?= =?us-ascii?Q?neAPAdZZyP53fEdd5P3sZb8lOETbBymzj11J6PRSz00R4kRBoboNPbWxGHh2?= =?us-ascii?Q?6sOrRZxACe4B1AsSVsI6DlI+1wNyLTxMPBtP2OgysutMrVU7eI5nFMR9fLi1?= =?us-ascii?Q?QZ/0gsVXsMA23kGsgvY8vYrguoyjZAaZIY3/+7eAQHUseot3/3AbdtM6JMHj?= =?us-ascii?Q?oKc4uqbG2O3mNALx+U+g00Hqo+6D+Ur/sFBBhS4uhKMhbrsOXjcYofgo0esm?= =?us-ascii?Q?yt6zaErJFB8Tn++h7Ii78Nwd1bJd8d4IKz/Gi6LuOqF40Io3Aq4FKsvTuHuk?= =?us-ascii?Q?QWbwzhYMoQjZVN87SkAgIBcs4UvyHjILXMT/xVzeL2iXjeVcasbZ//oNKszN?= =?us-ascii?Q?KYv/fVvJzgwNv27Wu6adtT1Ve3MnpwPs9kX5D/vvjK6Fihh3YovsOGHDvLGq?= =?us-ascii?Q?3vHSCMb1jSFbI1zQuvUR0TULPTZxKWr4+USqbazYLETj8VNfCtkCINZv1F3q?= =?us-ascii?Q?mW2zuzweld8ggCKbt2HNnMNIrNn1MEPOrygMkz5S1ruUO7QRQk2T9VrU9tin?= =?us-ascii?Q?zMVtwhRZPphmKhyEP2Vsr6T7e7/CRWCaYW/EHZF9MvQEBAhKOnzrRjYWUErJ?= =?us-ascii?Q?ELty5ZLdCAqrGjq74HKo6sK6Hdez0AOPCQRvqgRruZ6/fZ9hPdC7WO7tRAAa?= =?us-ascii?Q?5m4xdXXcp0PXERG/AIwdA0rbLlilATwghYiCHU4fpEUb9coenS0EAMansbFF?= =?us-ascii?Q?Zm7UL3pxyznfjFYumcEOUgRpNDX1e7D3udva83QYJDTyBB4TxHcImQr8OMBG?= =?us-ascii?Q?a8edFwgOh7ek7QdweTl4nM1f9kBDJx97SApUOVShadoJKtudifwGZ/R9lkXC?= =?us-ascii?Q?MqTyczxPOE7APQzGdnKd4vuoTHX1mw0uM8fAMh4l/05LicxYKPYFj8bsWJTy?= =?us-ascii?Q?3g6Rp/AeOUMk53YGmcbumqePvV8Gugd2gv3C2g2jGLkUtTQ1uBDPaar7aUtT?= =?us-ascii?Q?EY3Vp2HLBb0TmoGCAJYwGT4X17VHonX8U0TUN5BNp1dOu4hM1TCRem31kIc8?= =?us-ascii?Q?VRUQzhiSdrGYv5Fqq34GWmCFMuvRqubCg1SQb8c5kHd7uhtoMAvOgehjQM8/?= =?us-ascii?Q?n5RaUNUfKADAZCf4sY1eMmUhOyj2BkKqM8DQhdZdE5BmpXUfToqjAdeyVBBZ?= =?us-ascii?Q?rqnbSon6fSR5WMJPWTaewBek+zzk+RP/34Sk1RJlplbjOra73QXVIN177mfp?= =?us-ascii?Q?ci3F+rR36XrHpBhFw+cCIjcth5NGf/zy6wrVWFOuGl5adJY4V4xMAvvc32bD?= =?us-ascii?Q?IHYwkDhnPhZSy8+HfdDhE04dwQGdkEFdbT7xF+Cl?= X-OriginatorOrg: labware.com X-MS-Exchange-CrossTenant-Network-Message-Id: 0d7db9b9-952a-4bf0-1f68-08ddb27088c1 X-MS-Exchange-CrossTenant-AuthSource: SA1PR17MB5365.namprd17.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2025 16:10:55.9106 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: b5db0322-1aa0-4c0a-859c-ad0f96966f4c X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: THHL6upMdmR3VE5U5Wo7RoaTEOcVgAb4Kra5lbT8iSBOkfMo66bRe5zHiauWBZomSYEanhzVMJPw8ttTm/R9NA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR17MB4637 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: DAeMfCg4Jy0vufNp2TQVz0EVlwHI-OYVx9Mn0WXg5wQ_1750695057 X-Mimecast-Originator: labware.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=WINDOWS-1252 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 This commit introduces gdb.Compunit - a representation of struct compunit_symtab in Python. It also adds method gdb.Objfile.compunits() to get a list of compunits for an objfile and adds compunit attribute to gdb.Block and gdb.Symtab to access compunit containing given block or symbol table. Reviewed-By: Eli Zaretskii --- gdb/Makefile.in | 1 + gdb/NEWS | 2 + gdb/doc/python.texi | 75 ++++++ gdb/python/py-block.c | 14 + gdb/python/py-compunit.c | 311 ++++++++++++++++++++++ gdb/python/py-objfile.c | 31 +++ gdb/python/py-symtab.c | 14 + gdb/python/python-internal.h | 3 + gdb/testsuite/gdb.python/py-block.exp | 2 + gdb/testsuite/gdb.python/py-compunit-1.c | 24 ++ gdb/testsuite/gdb.python/py-compunit-2.c | 28 ++ gdb/testsuite/gdb.python/py-compunit.exp | 83 ++++++ gdb/testsuite/gdb.python/py-compunit.link | 10 + gdb/testsuite/gdb.python/py-symtab.exp | 8 + 14 files changed, 606 insertions(+) create mode 100644 gdb/python/py-compunit.c create mode 100644 gdb/testsuite/gdb.python/py-compunit-1.c create mode 100644 gdb/testsuite/gdb.python/py-compunit-2.c create mode 100644 gdb/testsuite/gdb.python/py-compunit.exp create mode 100644 gdb/testsuite/gdb.python/py-compunit.link diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 998203ce1e2..c74031891be 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -440,6 +440,7 @@ SUBDIR_PYTHON_SRCS =3D \ =09python/py-value.c \ =09python/py-varobj.c \ =09python/py-xmethods.c \ +=09python/py-compunit.c \ =09python/python.c =20 SUBDIR_PYTHON_OBS =3D $(patsubst %.c,%.o,$(SUBDIR_PYTHON_SRCS)) diff --git a/gdb/NEWS b/gdb/NEWS index e8e32a5dd5c..8e381329f9a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -333,6 +333,8 @@ vFile:stat ** Added gdb.Type.function. Returns a new gdb.Type representing a funct= ion returning that type. Parameter types can be specified too. =20 + ** Added class gdb.Compunit. + * Debugger Adapter Protocol changes =20 ** The "scopes" request will now return a scope holding global diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 633526dc875..3ef3699d355 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -220,6 +220,7 @@ optional arguments while skipping others. Example: * Blocks In Python:: Accessing blocks from Python. * Symbols In Python:: Python representation of symbols. * Symbol Tables In Python:: Python representation of symbol tables. +* Compunits In Python:: Python representation of compunits. * Line Tables In Python:: Python representation of line tables. * Breakpoints In Python:: Manipulating breakpoints using Python. * Finish Breakpoints in Python:: Setting Breakpoints on function return @@ -5828,6 +5829,11 @@ Like @code{Objfile.lookup_global_symbol}, but search= es for a global symbol with static linkage named @var{name} in this objfile. @end defun =20 +@defun Objfile.compunits () +Return a sequence of @code{gdb.Compunit} associated with this objfile. +@xref{Compunits In Python}. +@end defun + @node Frames In Python @subsubsection Accessing inferior stack frames from Python =20 @@ -6180,6 +6186,11 @@ have a superblock that is not the static block -- fo= r instance this happens for an inlined function. @end defvar =20 +@defvar Block.compunit +The @code{gdb.Compunit} containing this block. @xref{Compunits In Python}= . +This attribute is not writable. +@end defvar + @defvar Block.superblock The block containing this block. If this parent block does not exist, this attribute holds @code{None}. This attribute is not writable. @@ -6613,6 +6624,11 @@ If no producer information is available then @code{N= one} is returned. This attribute is not writable. @end defvar =20 +@defvar Symtab.compunit +The @code{gdb.Compunit} this symbol table belongs to. +@xref{Compunits In Python}. This attribute is not writable. +@end defvar + A @code{gdb.Symtab} object has the following methods: =20 @defun Symtab.is_valid () @@ -6642,6 +6658,65 @@ Return the line table associated with the symbol tab= le. @xref{Line Tables In Python}. @end defun =20 +@node Compunits In Python +@subsubsection Compunits representation in Python + +@cindex compunits in python +@tindex gdb.Compunit + +A compilation unit -- compunit for short -- represents a piece of code +compiled by compiler independently of the rest. It is a result of compilin= g +(parts of) one or more source files. + +Access to compunits maintained by @value{GDBN} on objfiles +is exposed to Python via @code{gdb.Compunit}. Compunit for a symbol table= can +be accessed via @code{compunit} property of @code{gdb.Symtab} object. +@xref{Symbol Tables In Python}. Method @code{compunits} of +@code{gdb.Objfile} can be used to get a list of all compunits belonging to +that objfile. @xref{Objfiles In Python}. + +A @code{gdb.Compunit} object has the following attributes: + +@defvar Compunit.objfile +The @code{gdb.Objfile} from which the compunit was extracted. +@xref{Objfiles In Python}. This attribute is not writable. +@end defvar + +@defvar Compunit.producer +The name and possibly version number of the program that +compiled the code in the compunit. +The contents of this string is up to the compiler. +If no producer information is available then @code{None} is returned. +This attribute is not writable. +@end defvar + +@defvar Compunit.symtabs +The sequence of @code{gdb.Symtab} objects associated with this compunit. +@xref{Symbol Tables In Python}. This attribute is not writable. +@end defvar + +A @code{gdb.Compunit} object has the following methods: + +@defun Compunit.is_valid () +Returns @code{True} if the @code{gdb.Compunit} object is valid, +@code{False} if not. A @code{gdb.Compunit} object can become invalid if +the compunit it refers to does not exist in @value{GDBN} any +longer. All other @code{gdb.Compunit} methods will throw an exception +if it is invalid at the time the method is called. Similarly, accessing +any of the attributes will throw an exception if it is invalid at the time +the attribute is accessed. +@end defun + +@defun Compunit.global_block () +Return @code{gdb.Block} object representing the global block of the +underlying compunit. @xref{Blocks In Python}. +@end defun + +@defun Compunit.static_block () +Return @code{gdb.Block} object representing the static block of the +underlying compunit. @xref{Blocks In Python}. +@end defun + @node Line Tables In Python @subsubsection Manipulating line tables using Python =20 diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c index fa7dd192280..89315ebf866 100644 --- a/gdb/python/py-block.c +++ b/gdb/python/py-block.c @@ -218,6 +218,18 @@ blpy_get_static_block (PyObject *self, void *closure) return block_to_block_object (static_block, self_obj->objfile); } =20 +/* Getter function for Block.compunit. */ + +static PyObject * +blpy_get_compunit (PyObject *self, void *closure) +{ + const struct block *block; + + BLPY_REQUIRE_VALID (self, block); + + return compunit_to_compunit_object (block->global_block ()->compunit ())= ; +} + /* Implementation of gdb.Block.is_global (self) -> Boolean. Returns True if this block object is a global block. */ =20 @@ -556,6 +568,8 @@ static gdb_PyGetSetDef block_object_getset[] =3D { "Block containing the global block.", NULL }, { "static_block", blpy_get_static_block, NULL, "Block containing the static block.", NULL }, + { "compunit", blpy_get_compunit, nullptr, + "Compunit containing this block.", nullptr }, { "is_static", blpy_is_static, NULL, "Whether this block is a static block.", NULL }, { "is_global", blpy_is_global, NULL, diff --git a/gdb/python/py-compunit.c b/gdb/python/py-compunit.c new file mode 100644 index 00000000000..a2d7620f483 --- /dev/null +++ b/gdb/python/py-compunit.c @@ -0,0 +1,311 @@ +/* Python interface to compunits. + + Copyright (C) 2025-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 . = */ + +#include "charset.h" +#include "symtab.h" +#include "source.h" +#include "python-internal.h" +#include "objfiles.h" +#include "block.h" + +struct compunit_object { + PyObject_HEAD + + /* The GDB compunit structure. */ + struct compunit_symtab *compunit; + + /* A compunit object is associated with an objfile, so keep track with + a single-linked list, rooted in the objfile. This allows + invalidation of the underlying struct compunit_symtab when the objfil= e is + deleted. */ + compunit_object *next; +}; + +/* This function is called when an objfile is about to be freed. + Invalidate the compunit as further actions on the compunit + would result in bad data. All access to obj->compunit should be + gated by CUPY_REQUIRE_VALID which will raise an exception on + compunits. */ +struct cupy_deleter +{ + void operator() (compunit_object *obj) + { + gdbpy_enter enter_py; + + while (obj !=3D nullptr) + { +=09compunit_object *next =3D obj->next; + +=09obj->compunit =3D nullptr; +=09obj->next =3D nullptr; +=09Py_DECREF (obj); + +=09obj =3D next; + } + } +}; + +extern PyTypeObject compunit_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("compunit_object"); +static const registry::key + cupy_objfile_data_key; + +/* Require a valid compunit. All access to compunit_object->compunit + should be gated by this call. */ + +#define CUPY_REQUIRE_VALID(compunit_obj, compunit)=09=09 \ + do {=09=09=09=09=09=09=09 \ + compunit =3D compunit_object_to_compunit (compunit_obj);=09 \ + if (compunit =3D=3D nullptr)=09=09=09=09=09 \ + {=09=09=09=09=09=09=09 \ +=09PyErr_SetString (PyExc_RuntimeError,=09=09 \ +=09=09=09 _("Compunit object is invalid.")); \ +=09return nullptr;=09=09=09=09=09 \ + }=09=09=09=09=09=09=09 \ + } while (0) + + +/* Getter function for gdb.Compunit.objfile. */ + +static PyObject * +cupy_get_objfile (PyObject *self, void *closure) +{ + struct compunit_symtab *compunit =3D nullptr; + + CUPY_REQUIRE_VALID (self, compunit); + + return objfile_to_objfile_object (compunit->objfile ()).release (); +} + +/* Getter function for gdb.Compunit.producer. */ + +static PyObject * +cupy_get_producer (PyObject *self, void *closure) +{ + struct compunit_symtab *compunit =3D nullptr; + + CUPY_REQUIRE_VALID (self, compunit); + if (compunit->producer () !=3D nullptr) + { + const char *producer =3D compunit->producer (); + + return host_string_to_python_string (producer).release (); + } + + Py_RETURN_NONE; +} + +/* Implementation of gdb.Compunit.is_valid (self) -> Boolean. + Returns True if this Symbol table still exists in GDB. */ + +static PyObject * +cupy_is_valid (PyObject *self, PyObject *args) +{ + struct compunit_symtab *compunit =3D nullptr; + + compunit =3D compunit_object_to_compunit (self); + if (compunit =3D=3D nullptr) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Return the GLOBAL_BLOCK of the underlying compunit. */ + +static PyObject * +cupy_global_block (PyObject *self, PyObject *args) +{ + struct compunit_symtab *compunit =3D nullptr; + + CUPY_REQUIRE_VALID (self, compunit); + + const struct blockvector *blockvector =3D compunit->blockvector (); + const struct block *block =3D blockvector->global_block (); + + return block_to_block_object (block, compunit->objfile ()); +} + +/* Return the STATIC_BLOCK of the underlying compunit. */ + +static PyObject * +cupy_static_block (PyObject *self, PyObject *args) +{ + struct compunit_symtab *compunit =3D nullptr; + + CUPY_REQUIRE_VALID (self, compunit); + + const struct blockvector *blockvector =3D compunit->blockvector (); + const struct block *block =3D blockvector->static_block (); + + return block_to_block_object (block, compunit->objfile ()); +} + +/* Return a list of gdb.Symtab objects associated with the underlying + compunit. */ + +static PyObject * +cupy_get_symtabs (PyObject *self, void *closure) +{ + struct compunit_symtab *compunit =3D nullptr; + + CUPY_REQUIRE_VALID (self, compunit); + + gdbpy_ref<> list (PyList_New (0)); + if (list =3D=3D nullptr) + return nullptr; + + for (struct symtab *each : compunit->filetabs ()) + { + gdbpy_ref<> item (symtab_to_symtab_object (each)); + if (item.get () =3D=3D nullptr +=09 || PyList_Append (list.get (), item.get ()) =3D=3D -1) +=09{ +=09 return nullptr; +=09} + } + + return list.release (); +} + +/* Given a compunit, and a compunit_object that has previously been + allocated and initialized, populate the compunit_object with the + struct compunit_symtab data. Also, register the compunit_object life-c= ycle + with the life-cycle of the object file associated with this + compunit, if needed. */ +static void +set_compunit (compunit_object *obj, struct compunit_symtab *compunit) +{ + obj->compunit =3D compunit; + obj->next =3D cupy_objfile_data_key.get (compunit->objfile ()); + cupy_objfile_data_key.set (compunit->objfile (), obj); + + Py_INCREF (obj); +} + +/* Return a new reference to gdb.Compunit Python object representing + COMPUNIT. Return NULL and set the Python error on failure. */ +PyObject * +compunit_to_compunit_object (struct compunit_symtab *compunit) +{ + gdb_assert (compunit !=3D nullptr); + + compunit_object *compunit_obj=20 + =3D cupy_objfile_data_key.get (compunit->objfile ()); + while (compunit_obj !=3D nullptr) + { + if (compunit_obj->compunit =3D=3D compunit) + { +=09 Py_INCREF (compunit_obj); +=09 return (PyObject*)compunit_obj; +=09} + compunit_obj =3D compunit_obj->next; + } + + compunit_obj =3D PyObject_New (compunit_object, &compunit_object_type); + if (compunit_obj) + set_compunit (compunit_obj, compunit); + + return (PyObject * )compunit_obj; +} + +/* Return struct compunit_symtab reference that is wrapped by this object.= */ +struct compunit_symtab * +compunit_object_to_compunit (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &compunit_object_type)) + return nullptr; + return ((compunit_object *) obj)->compunit; +} + +static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION +gdbpy_initialize_compunits (void) +{ + if (gdbpy_type_ready (&compunit_object_type) < 0) + return -1; + + return 0; +} + +GDBPY_INITIALIZE_FILE (gdbpy_initialize_compunits); + +=0C + +static gdb_PyGetSetDef compunit_object_getset[] =3D { + { "objfile", cupy_get_objfile, nullptr, "The compunit's objfile.", + nullptr }, + { "producer", cupy_get_producer, nullptr, + "The name/version of the program that compiled this compunit.", nullpt= r }, + { "symtabs", cupy_get_symtabs, nullptr, + "List of symbol tables associated with this compunit", nullptr }, + {nullptr} /* Sentinel */ +}; + +static PyMethodDef compunit_object_methods[] =3D { + { "is_valid", cupy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this compunit is valid, false if not." }, + { "global_block", cupy_global_block, METH_NOARGS, + "global_block () -> gdb.Block.\n\ +Return the global block of the compunit." }, + { "static_block", cupy_static_block, METH_NOARGS, + "static_block () -> gdb.Block.\n\ +Return the static block of the compunit." }, + {nullptr} /* Sentinel */ +}; + +PyTypeObject compunit_object_type =3D { + PyVarObject_HEAD_INIT (nullptr, 0) + "gdb.Compunit",=09=09 /*tp_name*/ + sizeof (compunit_object),=09 /*tp_basicsize*/ + 0,=09=09=09=09 /*tp_itemsize*/ + 0,=09=09=09=09 /*tp_dealloc*/ + 0,=09=09=09=09 /*tp_print*/ + 0,=09=09=09=09 /*tp_getattr*/ + 0,=09=09=09=09 /*tp_setattr*/ + 0,=09=09=09=09 /*tp_compare*/ + 0,=09=09=09=09 /*tp_repr*/ + 0,=09=09=09=09 /*tp_as_number*/ + 0,=09=09=09=09 /*tp_as_sequence*/ + 0,=09=09=09=09 /*tp_as_mapping*/ + 0,=09=09=09=09 /*tp_hash */ + 0,=09=09=09=09 /*tp_call*/ + 0,=09=09=09 /*tp_str*/ + 0,=09=09=09=09 /*tp_getattro*/ + 0,=09=09=09=09 /*tp_setattro*/ + 0,=09=09=09=09 /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT,=09=09 /*tp_flags*/ + "GDB compunit object",=09 /*tp_doc */ + 0,=09=09=09=09 /*tp_traverse */ + 0,=09=09=09=09 /*tp_clear */ + 0,=09=09=09=09 /*tp_richcompare */ + 0,=09=09=09=09 /*tp_weaklistoffset */ + 0,=09=09=09=09 /*tp_iter */ + 0,=09=09=09=09 /*tp_iternext */ + compunit_object_methods,=09 /*tp_methods */ + 0,=09=09=09=09 /*tp_members */ + compunit_object_getset,=09 /*tp_getset */ + 0,=09=09=09=09 /* tp_base */ + 0,=09=09=09=09 /* tp_dict */ + 0,=09=09=09=09 /* tp_descr_get */ + 0,=09=09=09=09 /* tp_descr_set */ + 0,=09=09=09=09 /* tp_dictoffset */ + 0,=09=09=09=09 /* tp_init */ + 0,=09=09=09=09 /* tp_alloc */ + PyType_GenericNew=09=09 /* tp_new */ +}; diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c index 1c6f5697302..b76f57e818d 100644 --- a/gdb/python/py-objfile.c +++ b/gdb/python/py-objfile.c @@ -544,6 +544,33 @@ objfpy_repr (PyObject *self_) =09=09=09 objfile_name (obj)); } =20 +/* Implementation of gdb.Objfile.compunits() -> List */ + +static PyObject * +objfpy_compunits (PyObject *self_, PyObject *args) +{ + objfile_object *self =3D (objfile_object *) self_; + + OBJFPY_REQUIRE_VALID (self); + + gdbpy_ref<> list (PyList_New (0)); + if (list =3D=3D nullptr) + return nullptr; + + self->objfile->expand_all_symtabs (); + + for (struct compunit_symtab *compunit : self->objfile->compunits ()) + { + PyObject *item =3D compunit_to_compunit_object (compunit); + + if (item =3D=3D nullptr +=09 || PyList_Append (list.get (), item) =3D=3D -1) +=09return nullptr; + } + + return list.release (); +} + /* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it. Return non-zero if STRING is a potentially valid build id. */ =20 @@ -737,6 +764,10 @@ Look up a global symbol in this objfile and return it.= " }, "lookup_static_symbol (name [, domain]).\n\ Look up a static-linkage global symbol in this objfile and return it." }, =20 + { "compunits", objfpy_compunits, METH_NOARGS, + "compunits () -> List.\n\ +Return a sequence of compunits associated to this objfile." }, + { NULL } }; =20 diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c index 9f7bdb0f132..806a6efa4fd 100644 --- a/gdb/python/py-symtab.c +++ b/gdb/python/py-symtab.c @@ -149,6 +149,18 @@ stpy_get_producer (PyObject *self, void *closure) Py_RETURN_NONE; } =20 +/* Getter function for Symtab.compunit. */ + +static PyObject * +stpy_get_compunit (PyObject *self, void *closure) +{ + struct symtab *symtab =3D nullptr; + + STPY_REQUIRE_VALID (self, symtab); + + return compunit_to_compunit_object (symtab->compunit ()); +} + static PyObject * stpy_fullname (PyObject *self, PyObject *args) { @@ -448,6 +460,8 @@ static gdb_PyGetSetDef symtab_object_getset[] =3D { NULL }, { "producer", stpy_get_producer, NULL, "The name/version of the program that compiled this symtab.", NULL }, + { "compunit", stpy_get_compunit, nullptr, + "The compunit this symtab belongs to.", nullptr }, {NULL} /* Sentinel */ }; =20 diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 7f4237eecc2..99e362c5221 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -548,6 +548,8 @@ gdbpy_ref create_thread_object (struct t= hread_info *tp); gdbpy_ref<> thread_to_thread_object (thread_info *thr);; gdbpy_ref inferior_to_inferior_object (inferior *inf); =20 +PyObject *compunit_to_compunit_object (struct compunit_symtab *compunit); + PyObject *gdbpy_buffer_to_membuf (gdb::unique_xmalloc_ptr buffer= , =09=09=09=09 CORE_ADDR address, ULONGEST length); =20 @@ -564,6 +566,7 @@ struct symtab *symtab_object_to_symtab (PyObject *obj); struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj); frame_info_ptr frame_object_to_frame_info (PyObject *frame_obj); struct gdbarch *arch_object_to_gdbarch (PyObject *obj); +struct compunit_symtab *compunit_object_to_compunit (PyObject *obj); =20 extern PyObject *gdbpy_execute_mi_command (PyObject *self, PyObject *args, =09=09=09=09=09 PyObject *kw); diff --git a/gdb/testsuite/gdb.python/py-block.exp b/gdb/testsuite/gdb.pyth= on/py-block.exp index ce3f7ce04c4..11c2de8fc6f 100644 --- a/gdb/testsuite/gdb.python/py-block.exp +++ b/gdb/testsuite/gdb.python/py-block.exp @@ -104,6 +104,8 @@ gdb_test "python print (repr (block))" \ "Check block in many_locals_func" gdb_test "python print (block.function)" "many_locals_func" \ "many_locals_func block" +gdb_test "python print(block.compunit)" "" \ + "test compunit property" =20 # Switch frames, then test for main block. gdb_test "up" ".*" diff --git a/gdb/testsuite/gdb.python/py-compunit-1.c b/gdb/testsuite/gdb.p= ython/py-compunit-1.c new file mode 100644 index 00000000000..f0f43fdd4ff --- /dev/null +++ b/gdb/testsuite/gdb.python/py-compunit-1.c @@ -0,0 +1,24 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2025-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 . = */ + +int give_me_zero (); + +int +main () +{ + return give_me_zero (); +} diff --git a/gdb/testsuite/gdb.python/py-compunit-2.c b/gdb/testsuite/gdb.p= ython/py-compunit-2.c new file mode 100644 index 00000000000..f38a49ea30f --- /dev/null +++ b/gdb/testsuite/gdb.python/py-compunit-2.c @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2025-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 . = */ + +int __attribute__ ((section (".text_give_me_one"))) __attribute__((noinlin= e)) +give_me_one () +{ + return 1; +} + +int __attribute__ ((section (".text_give_me_zero"))) +give_me_zero () +{ + return give_me_one() - 1; +} diff --git a/gdb/testsuite/gdb.python/py-compunit.exp b/gdb/testsuite/gdb.p= ython/py-compunit.exp new file mode 100644 index 00000000000..9e5c4dc6e03 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-compunit.exp @@ -0,0 +1,83 @@ +# Copyright (C) 2025-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 . + +# This file is part of the GDB testsuite. It tests the compunit +# support in Python. + +load_lib gdb-python.exp + +require allow_python_tests + +# The test executable is compiled using two source files and uses custom +# linker script. This is to force creation of two interleaved compunits +# (py-compunit-1.c) with one function (main) and the other (py-compunit-2.= c) +# with two functions (get_me_one and get_me_zero) which are placed "before= " +# and "after" the main function. + +standard_testfile py-compunit-1.c py-compunit-2.c + +set ld_flags "-static -T${srcdir}/${subdir}/py-compunit.link" +if { [prepare_for_testing "failed to prepare" ${testfile} \ +=09[list $srcfile $srcfile2] \ +=09[list debug additional_flags=3D$ld_flags]]} { + return -1 +} + +if {![runto_main]} { + return 0 +} + +set python_error_text "Error occurred in Python.*" + +gdb_py_test_silent_cmd "python sym =3D gdb.lookup_symbol(\"main\")" \ + "Find a symbol in objfile" 1 +gdb_py_test_silent_cmd "python objfile =3D sym\[0\].symtab.objfile" \ + "Get backing object file" 1 + +gdb_test "python print (len(objfile.compunits()) > 0)" \ + "True" \ + "Get objfile compunits" +gdb_test "python print (objfile.compunits())" \ + "\\\[\\\]" \ + "Objfile compunits return a sequence of gdb.Compunit" +gdb_py_test_silent_cmd "python compunit =3D objfile.compunits()\[0\]" \ + "Get first compunit" 1 +gdb_test "python print (compunit.is_valid())" \ + "True" \ + "Compunit is valid" =20 +gdb_test "python print (compunit =3D=3D compunit)" \ + "True" \ + "Compunits are comparable" +gdb_test "python print (compunit is objfile.compunits()\[0\])" \ + "True" \ + "Compunits are identical" +gdb_test "python print (len(objfile.compunits()\[0\].symtabs) > 0)" \ + "True" \ + "Get compunit symtabs" +gdb_test "python print (objfile.compunits()\[0\].symtabs)" \ + "\\\[\\\]" \ + "Compunit symtabs return a sequence of gdb.Symtab" + + +gdb_unload "unload 1" + +gdb_test "python print (objfile.is_valid())" "False" \ +"Get objfile validity after unload" +gdb_test "python print (compunit.is_valid())" "False" \ +"Get compunit validity after unload" +gdb_py_test_silent_cmd "python compunit =3D None" \ +"Test compunit deallocation" 1 +gdb_test "python print (objfile.compunits())" "RuntimeError.*: Objfile no = longer exists.*" \ +"Get objfile compunits after unload" diff --git a/gdb/testsuite/gdb.python/py-compunit.link b/gdb/testsuite/gdb.= python/py-compunit.link new file mode 100644 index 00000000000..5b219acf916 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-compunit.link @@ -0,0 +1,10 @@ +SECTIONS +{ + .text_give_me_zero 0x00080000 : { } +} INSERT BEFORE .text; + +SECTIONS +{ + .text_give_me_one 0x00F00000 : { } +} +INSERT AFTER .text; diff --git a/gdb/testsuite/gdb.python/py-symtab.exp b/gdb/testsuite/gdb.pyt= hon/py-symtab.exp index a4891f31288..4828a0a33b6 100644 --- a/gdb/testsuite/gdb.python/py-symtab.exp +++ b/gdb/testsuite/gdb.python/py-symtab.exp @@ -68,6 +68,8 @@ gdb_test "python print (sal.is_valid())" "True" "test sal= .is_valid" gdb_test "python print (symtab.filename)" ".*${py_symbol_c}" "test symtab.= filename" gdb_test "python print (symtab.objfile)" \ "" "test symtab.objfile" +gdb_test "python print (symtab.compunit)" \ + "" "test symtab.compunit" gdb_test "python print (symtab.fullname())" ".*${full_py_symbol_c}" "test = symtab.fullname" gdb_test "python print (symtab.is_valid())" "True" "test symtab.is_valid()= " gdb_test "python print (\"qq\" in global_symbols)" "True" "test qq in glob= al symbols" @@ -89,6 +91,12 @@ gdb_test_multiple "python print (\"simple_struct\" in st= atic_symbols)" \ =09 } =09} } +gdb_test "python print (symtab.compunit in symtab.objfile.compunits())" \ + "True" "Test symtab.compunit in symtab.objfile.compunits()" +gdb_test "python print (symtab.compunit.global_block() is symtab.global_bl= ock())" \ + "True" "Test symtab.compunit.global_block() is symtab.global_block()" +gdb_test "python print (symtab.compunit.static_block() is symtab.static_bl= ock())" \ + "True" "Test symtab.compunit.static_block() is symtab.static_block()" =20 # Test symtab identity gdb_test "python print (symtab is symtab)"\ --=20 2.47.2