From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 102050 invoked by alias); 16 Oct 2017 22:22:27 -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 102039 invoked by uid 89); 16 Oct 2017 22:22:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.3 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_STOCKGEN autolearn=ham version=3.3.2 spammy=releasing, demands, windy, backing X-HELO: sesbmg22.ericsson.net Received: from sesbmg22.ericsson.net (HELO sesbmg22.ericsson.net) (193.180.251.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 16 Oct 2017 22:22:23 +0000 Received: from ESESSHC012.ericsson.se (Unknown_Domain [153.88.183.54]) by sesbmg22.ericsson.net (Symantec Mail Security) with SMTP id CD.D8.07039.C1135E95; Tue, 17 Oct 2017 00:22:20 +0200 (CEST) Received: from EUR01-HE1-obe.outbound.protection.outlook.com (153.88.183.145) by oa.msg.ericsson.com (153.88.183.54) with Microsoft SMTP Server (TLS) id 14.3.352.0; Tue, 17 Oct 2017 00:22:19 +0200 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=simon.marchi@ericsson.com; Received: from [142.133.49.59] (192.75.88.130) by DBXPR07MB320.eurprd07.prod.outlook.com (2a01:111:e400:941d::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.77.5; Mon, 16 Oct 2017 22:22:16 +0000 Subject: Re: [python][patch] Python rbreak To: Phil Muldoon , "gdb-patches@sourceware.org" References: From: Simon Marchi Message-ID: Date: Mon, 16 Oct 2017 22:22: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: Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-ClientProxiedBy: MWHPR14CA0004.namprd14.prod.outlook.com (2603:10b6:300:ae::14) To DBXPR07MB320.eurprd07.prod.outlook.com (2a01:111:e400:941d::21) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: ab371c3e-0617-4469-4ecf-08d514e45c73 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(2017030254152)(2017052603199)(201703131423075)(201703031133081)(201702281549075);SRVR:DBXPR07MB320; X-Microsoft-Exchange-Diagnostics: 1;DBXPR07MB320;3:Ufmcbaz8u5I1BghUdQ/PB1t4mHVUxSY9+LNpVeZa35phG/mC9Y3lrddRJhNlme0g21J00zY3Lawz+ab2JvW2+/9q1Mp2jADbGFBuK6AGKy0xNFmL3cM9D0RnwLIny6go/Ab+5RxhTUI0KCoKRO9fNiY+n1IomE39MKQt3FUUt7tTddiC4YynzukWO19F6aW4ZVBlwhWzMXzbhhAf6qX1/vCymzsbFUzFK6Bf+7NZv/U1LhPVNOyCjXbdkqDi8cwr;25:S30lDWtBErLj7+zZf9SgzlbtIQ86ZMaJThp9GCy/zOPH/gi9PjWS8IS88NwKNUczDH40g0cqNcpQZ8OLjeFwKea+nMcCu+CewPOyLbKTU3j31e8Y/otnmqkCaUR8Z9CoBS/7kT7dHGF+NAImkzRImMyecCHlW42xXhZLJJXiNMKnP5okLhcYAaLjY3DzF8xO9X+BWlevUZi40W88O2uTJXcTG8e1cgflqr5OLOWybWsNHcWRFf1uwW8XnTaUUcDA8eGhCETYye0N/mmpLzgxjaclAf5xo4k5CdoKSy2rFZYcHgnunKGVzzFNvwTT+9MDBfrzivQYcgeIctH7l+uLF58hYKLixT8QtG6ksqTGR1o=;31:t6w19IjE0uH2m9nTZvwJes+aWKy/d3DLae6H5WLle9GqRkzEHq8UjmaU8Jvgmi5AbqB0GD2Bs9tvX2VjirPqYKx8p5fkZ/SC6/oWVH/Yn+eW5U391PQKFAcyJURpv/7d6rqeVDpCL8h1/kHZmhXc4UoCOfW4zFgU0n2hjNMb/1MPu0PPxWlslEUx6BUAoKfQ9waGuGMZlXXieeMbXJAheknZT7sIw1newEkawdDI5mU= X-MS-TrafficTypeDiagnostic: DBXPR07MB320: X-Microsoft-Exchange-Diagnostics: 1;DBXPR07MB320;20:ZHSvN9inmIO+dY1c4tq7DJhsNgaiPXIeKaxUYI6QVmysG/S4Ddq8q+HkVtgKvNYXAXg+VgHFUdIzI5Vah/c8sjTgxgPXgRzIlC+WrfIiIUmWgee+LSKznweXGMDs9j6VrnwU8gFxRnYLGNXy5KOD8ksOGsLkzF9pITKHbUsC7EyJttmhnZIf/dqUO0l3KWklKgSxXlBptDECQ6byE1xGTrJHI+21hHXDnw65OPx1AUE6ukSkZCHVdqtm8OiYBcccSdZvg8IdX+/yr6e7QtRHukkHz25mwcZYS+BeIgsvd76nLPuEakBa+MA59UnctJszo5rovghCIxforFeeeFoAa0pNQIeon3XWm2ATQqY6xkqbVrLSti0hMG+0QS1DpfTk+w98TPHWelI9wlUtGIu0kfSw5joszPSv8vqqzVT3wdblaQ++x8nVP3kdDm5AG09mvOWZdi0PXO8Cm+vDu8ZFmkmRj6xOnurrvKM5Hz45XoLPnAcLyaBo8rJJXzb4b8H/;4:bfnSDXzaMH/sfeEOziw/jkp7VaKbnFVdE19va4FTHw8RG0qrQtaNJH6GK9JeP+5IezbAY7QNJaLZhyKTi5lXzEB3zrcznwpoOXEEvsNk2Rd/AFmQwN4KKAv96qglzxG86HlEBrpuqD9THK7Wtm/s3EfUK+Q/hJMOLDyTe10cdVsXIAhiEYl7sdTYmnPglAN5GWisWyFyDnTbsAfxdQ4jBmQGXWjYkwH/H9jKomS9j2GTHbA+5JjjBY+tdgF9bGAF2hoJOFcQUT8V6G5t0mP5n2iqFDKa1QKbu19wiP+OGUHiNZGwszMim7FudK35UxHr2icC7/IKrsDuGNh37oHworMeJd+axzDqiuISbVtK0NDo+9AyLmMFPokJhGl94eKL X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(22074186197030)(131327999870524); X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(8121501046)(5005006)(100000703101)(100105400095)(3002001)(10201501046)(93006095)(93001095)(6041248)(20161123558100)(20161123560025)(20161123555025)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:DBXPR07MB320;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:DBXPR07MB320; X-Forefront-PRVS: 0462918D61 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6049001)(6009001)(39860400002)(376002)(346002)(189002)(377424004)(377454003)(199003)(24454002)(31686004)(105586002)(101416001)(76176999)(54356999)(50986999)(47776003)(23676002)(3846002)(8936002)(81166006)(65956001)(6116002)(66066001)(49976008)(25786009)(81156014)(8676002)(5890100001)(2501003)(36756003)(189998001)(106356001)(65806001)(478600001)(230700001)(33646002)(68736007)(65826007)(86362001)(6246003)(305945005)(4001150100001)(97736004)(229853002)(316002)(31696002)(53936002)(5660300001)(6486002)(7736002)(53546010)(6306002)(64126003)(110136005)(16576012)(2950100002)(16526018)(83506001)(6666003)(58126008)(50466002)(2906002)(78286006)(403724002)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:DBXPR07MB320;H:[142.133.49.59];FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; Received-SPF: None (protection.outlook.com: ericsson.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtEQlhQUjA3TUIzMjA7MjM6RjdIejNoUVk1NnlCTjZlRU1vZW12QlJQN3Ur?= =?utf-8?B?alVydng4bHg1Wi9YY2R0MHVzSXVQbWgvWmVCSGViN3VrNmM1dGFXNTRjUElt?= =?utf-8?B?aGxYTE1jZFBjZHFHMElrbXlodC84WENtVGVWem1BTUJwVWp5cEJVV0RucDBQ?= =?utf-8?B?OXJSekg0ODhkOU5sWk5VTzdHR0tLMEtSRm1qRlkrb3d6SkNnUGlFVHZURXJn?= =?utf-8?B?QzY2YzNiOTF3VjN0NTlEdDBuRUE3NStaa1ExVGZ5andIaDVMZmk3NXN4Sy9S?= =?utf-8?B?dWx2ZWVaLy9lQ0dzbmxSSXloZ3VKUExqbU5IOXR2VFZQQ1pPL01sOXg3NFQ1?= =?utf-8?B?V2tIOSt4di9zVS8rY2VZRlBFam9EQmZUUlZqYzRnYTVwNUZtK0hxYjJOVENa?= =?utf-8?B?RzdXb0YyODVhTVAxTUtlSlYyQkhJemZoWFgvd3U4aTNUcFdmUTdFdTdINkZl?= =?utf-8?B?Tm1UOEtUTkhGMW9XRzAza2ZhS1gwQkJDZ2phNzdYMXpnNHprK0FXV1dweGZu?= =?utf-8?B?WUFPa2FmSDI5aWFNejA3R3hxOEN1c1pyRzJkUUViOWtQelJiR3RTcHBNd2xx?= =?utf-8?B?QnVwVW1yS3plcS9vaUs0bWVHdHlCWXpSUVNvZXl3SmhteHg5R2UraEpGN0Vk?= =?utf-8?B?RFJWNHQvdDN1bC9oNjhObkN3dWptYnR6QjFjeElyM2o0TklLVUd0YU9BTHVj?= =?utf-8?B?QmM1QzlEUVZsL3lzWlpJVS9ZbUJsTFRwTVJmb2RuSlFEbEtXVjlocmRvaHcz?= =?utf-8?B?MWcrdEppWkZjY3VHa2NyRHoyekhxOW1nQW9JanNZN3F6a1IxZ3FLQkN5bXQ4?= =?utf-8?B?SkUyZ2N4c0hhUUhlOFdWM0lnMllqd3F1WVNkczMyVUFmYllpaUREN1FJeEho?= =?utf-8?B?dVk5RktjTXRYWmRHR3pXZ2dtem16cFZvckdpK2NlbHpGYTRsMnZ0SzQ1NTc4?= =?utf-8?B?aWpGZkFJdUN6SHpEK29jWDdBZERndlZZamYrQjU2UUlPR0hPNGsvRXdMeXBo?= =?utf-8?B?K3lDYjExemp0Rk5FQ0txL2lmdTNwSTBnamNRc2lvVVdoSjlYcm9xNndIdlUw?= =?utf-8?B?WTR2MWViM1I2NTJnQStWWHdsMTduMHFkYmtJZ3lQSkFPWktLVjJUSVZvTDNT?= =?utf-8?B?aVBSd1pCaVRaUmFWS2RmTjNGcVdsUlg0N1pQeGFpMDVuMXhMc3dQUFViSWRR?= =?utf-8?B?TmlVMkNmTGtjbUVER3JjMFdlaFdYampncENVdjJ5VkhtYUV4MEZjbUhCbGNx?= =?utf-8?B?VWN1ZGtSVkpSbjZCaFd4aStxWXdoMUttUDdJWDM2ekorbldGblZkMitpOE0y?= =?utf-8?B?TTE4QzFOYlE3WTVWQmJQUEpOMm5GN0oycTFLUXZ3T3Q3UnlvVnRadkxKQk9h?= =?utf-8?B?ellyZFh0SUY5WldnbnRqazBCbFhiUS91c0pyUmx2SDhVcjRXaTVPZkNaNHNt?= =?utf-8?B?YTVPZlRva0FBL0ZsbkdxbjlEbUhBY0I4KzgwZGNHdFh4TUJDdUdPd0lLRVA3?= =?utf-8?B?MDVYMUxweERoMVkrdjQ1a3g4RU1yMlErR1lJUm16Vjlvb3QyT2lKMm44eCtB?= =?utf-8?B?bms5THVCZ0Y5VjZ1KzYrNU1WdHZ6T1BKbE0zUytmRUgwZHVROVhlQWFrNHZm?= =?utf-8?B?NGQvSXFCNmlRcXhrM1B1dUczdE9ZQXhkSVRSYzIycG55eEJicTg3TnlwR3Nx?= =?utf-8?B?NWswbTRLTVh3SzNOVUxHZVZuR2hBOU5FMDVVYTl1bWNoNkoxRkRGWjBpS252?= =?utf-8?B?aXh0NGRjdncwOXE2Vkp0eDZhTFVaZUlWK3RrMmFQVk1sb21tZS83dUl1MWlT?= =?utf-8?B?RXdiOVFSRVRVTWlJRTZtUUJKY2ExQk8yS01Xczk0dW9qb0JqLzZ5aW1uV2M5?= =?utf-8?B?a0VXbmU1Y3RqNkRaWTY3NHFSQXFGT0dxSlRrUFJXa1ZzK1VsOTNra20xdGlF?= =?utf-8?B?clRhRVZuc2lLZjVzb3ZyTUJNRmJhUGhMUExqZXJZanpmSzZobW05NjZNSTNs?= =?utf-8?B?WkVaN1piaWNUK0RMdGN1T2QrSVEwM2xJS0NpakVVQitjbzFIcm9JZzU5c2Fy?= =?utf-8?Q?Qd0HQgHKVvVAP0QWX1kIl/sL?= X-Microsoft-Exchange-Diagnostics: 1;DBXPR07MB320;6:XH/Lk81xn/1Gb5h2tK+gST3QxxqTeqJTaWpM7CrQEnuUazmaqVPSjY6lylGlBCrvLceq06Kx47EfWJn32BFEOqINFNDhG0/Vpv4dVdyaSeHz1MpKXhcVF1Ow+oAby0Ey3O1ScpqzeleVud57eUcmuxAzOy2oxESZhvk7NQesHpsyIW3TcJJWKa/Gl8yuF1MXCPFM/FIfBJpuwn2BqTp72Jc767SJ8aiEz/jWVIpHo4DcY32S1ZEldt1RnTIyZ7aikqf8bQHbZ8N61g/fPjSsbkAANX7qdZLD8rWCebfZ0lm1fw721hDKb+PsaIKRfO2U6OUmWWrlL0PEoqAzSAePyA==;5:eaPx32Vg1POdZrH4E1Lp03GfQ/ELRsN+yC/iascpwN7dgcKmgrNu++2RF/AtOqbFiIP9VnRttgUy6xZ1orjbTIpWSXECwjp8h1+ux/MaEnRlQt2vVYL2t5vpfTngX6syXKMknKHUd/eLk9zhfmpV1w==;24:6CgaOJ81gnPyFO1sL+8F1ON0EktH0Z53FDUklONT0KDPGg9v7AkClM2O1SOdRE+Z2PDjTo7TD2TghXAJJf9a6CRJ6+A8LV2sT4S9LmCePf0=;7:q1YWtZOpCO+9Xi/SZcF0snKxYvkP5ZDiGObDAlc0HjhkUf5m3fHOqti79OoZSF5IVLufqZGYyccsLSFUb0ur5/3H/puC13TnwcKxjIJXAJyaf2YhF2JFRDoigtZ4jIqn8kvM3N01oYAT0vjsIvVJgBlzHYn46SAmhrKnkDiBIO3Xegkt+7cnZqaC3Knej4JiJaUqm0BiqfB5FiOIudSWvidU60S36SYRO8UFeb3gHiE= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Oct 2017 22:22:16.8484 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBXPR07MB320 X-OriginatorOrg: ericsson.com X-IsSubscribed: yes X-SW-Source: 2017-10/txt/msg00481.txt.bz2 On 2017-10-11 07:30 AM, Phil Muldoon wrote: > This introduces a Python rbreak function to the Python API. Its > functionality was designed to closely match that of the console rbreak > but with a number of caveats. > > That being said, there's a bit of preamble first. > > My original design was to have the gdb.Breakpoint constructor take a > regex pattern. While breakpoints can, and do, have multiple locations > they are always tied in with one linespec. I looked at the > linespec/location code and the relationship is pretty firmly embedded > as a one to many relationship. One linespec can have multiple > locations but only one linespec can be represented in the location > object. (Or address or probe or whatever the location is > representing). A linespec has to be definitive; it has to point to one > symbol. I thought about modifying this to have multiple symbols and > multiple locations but quickly decided this was really going to > violate the design contract of linespecs/location. It would also be > considerable and disruptive work. I looked then, again, at a > breakpoint having multiple linespecs but again decided the amount of > disruption this would generate was not worth a Python rbreak returning > one breakpoint representing multiple symbols and multiple locations. > > So, instead, I've made the Python rbreak functionality a little more > tuneable than the console command equivalent. The first tuneable is to > allow the user to exclude mini symbols from the pattern matching. A > loosely written pattern passed to the console rbreak command can > generate 5000+ breakpoints from a simple C "hello world" > program. rbreak "" will place a breakpoint on every single mini symbol > representing a function. I can't possibly see why this would be > desirable. In order to facilitate broadly-written patterns that seek to > place a breakpoint on every user-defined function, the equivalent > would be: > > gdb.rbreak ("", minisyms=False) Hi Phil, As Kevin noted (IIUC), this should be "minsyms" if we want to follow standard GDB terminology. > > That would place a breakpoint on all functions that are actually > defined in the inferior (and not those that are inserted by the > compiler, linker, etc). The default for this keyword is False. > > The second tuneable is a throttle. Beyond the name (which I am unsure > about but could not think of a better one), this allows the user to > enter a fail-safe limit for breakpoint creation. So, for the following > example, an inferior with ten user provided functions: > > gdb.rbreak ("", minisyms=False, throttle=5) max_results? max_breakpoints? > Would set no breakpoints and raise a runtime error. This functionality > is more aimed at those who want to utilise Python rbreak from a > toolset perspective (say for a GDB UI). The default for this keyword > is unlimited. > > The last tuneable is the ability to limit the pattern matching to a > set of gdb.Symtab objects. So, given the example below: > > gdb.rbreak ("", minisyms=False, throttle=5, symtabs=symTuple) > > where "symTuple" is a tuple of gdb.Symtab objects, the search/pattern > matching would be restricted to those gdb.Symtab objects only. The > default for this keyword (i.e, no keyword provided) is to search all > symbol tables. > > All of the examples above have "" as the search pattern but you can, > of course, specify any valid GDB regex there. > > On a review note I seek a little advice on the interface to > search_symbols. If the user does provide a symtabs keyword, the code > collects the name of the file attached to each symtab specified. It > does that through the usual Python method > (python_string_to_target_string). That returns a > gdb::unique_xmalloc_ptr. I planned to store these in a > std::vector, however, I was unable to coerce a > std::vector> into a char **p[] > representation the search_symbols function requires. I ended up > releasing the object (that results in a char *) and wrapping the > std::vector in a simple type that provides a destructor to properly > free the released strings when the object falls out of scope. I > thought about just changing the search_symbols interface to accept a > vector of (gdb) unique pointers but noted a C++ run had already been > performed over the function. Any thoughts here would be appreciated. > > Long, windy, preamble over the patch follows at the end of the email. > > Cheers > > Phil > > -- > > 2017-10-11 Phil Muldoon > > * python/python.c (gdbpy_rbreak): New function. > > 2017-10-11 Phil Muldoon > > * gdb.python/py-rbreak.exp: New file. > * gdb.python/py-rbreak.c: New file. > * gdb.python/py-rbreak-func2.c: New file. > > 2017-10-11 Phil Muldoon > > * python.texi (Basic Python): Add rbreak documentation. > > -- > > diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi > index f661e489bb..b2d4516886 100644 > --- a/gdb/doc/python.texi > +++ b/gdb/doc/python.texi > @@ -243,6 +243,24 @@ were no breakpoints. This peculiarity was subsequently fixed, and now > @code{gdb.breakpoints} returns an empty sequence in this case. > @end defun > > +@findex gdb.rbreak > +@defun gdb.rbreak (regex @r{[}, minisyms @r{[}, throttle, @r{[}, symtabs @r{]]]}) > +Return a Python tuple holding a collection of newly set > +@code{gdb.Breakpoint} objects matching function names defined by the > +@var{regex} pattern. If the @var{minisyms} keyword is @code{True}, > +all system functions (those not explicitly defined in the inferior) > +will also be included in the match. The @var{throttle} keyword takes > +an integer that defines the maximum number of pattern matches for > +functions matched by the @var{regex} pattern. If the number of > +matches exceeds the integer value of @var{throttle}, a > +@code{RuntimeError} will be raised and no breakpoints will be created. > +If @var{throttle} is not defined then there is no imposed limit on the > +maximum number of matches and breakpoints to be created. The > +@var{symtabs} keyword takes a Python iterable that yields a collection > +of @code{gdb.Symtab} objects and will restrict the search to those > +functions only contained within the @code{gdb.Symtab} objects. > +@end defun > + > @findex gdb.parameter > @defun gdb.parameter (parameter) > Return the value of a @value{GDBN} @var{parameter} given by its name, > diff --git a/gdb/python/python.c b/gdb/python/python.c > index b04057ec4a..4d591df30c 100644 > --- a/gdb/python/python.c > +++ b/gdb/python/python.c > @@ -642,6 +642,191 @@ gdbpy_solib_name (PyObject *self, PyObject *args) > return str_obj; > } > > +/* Implementation of Python rbreak command. Take a REGEX and > + optionally a MINISYMS, THROTTLE and SYMTABS keyword and return a > + Python tuple that contains newly set breakpoints that match that > + criteria. REGEX refers to a GDB format standard regex pattern of > + symbols names to search; MINISYMS is an optional boolean (default > + False) that indicates if the function should search GDB's minimal > + symbols; THROTTLE is an optional integer (default unlimited) that > + indicates the maximum amount of breakpoints allowable before the > + function exits (note, if the throttle bound is passed, no > + breakpoints will be set and a runtime error returned); SYMTABS is > + an optional iterator that contains a set of gdb.Symtabs to iterator or iterable? It would make sense to be able to pass a list here, for example. > + constrain the search within. */ > + > +static PyObject * > +gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw) > +{ > + /* A simple type to ensure clean up of a vector of allocated strings > + when a C interface demands a const char *array[] type > + interface. */ > + struct symtab_list_type > + { > + ~symtab_list_type () > + { > + for (const char *elem: vec) > + xfree ((void *) elem); > + } > + std::vector vec; > + }; > + > + char *regex = NULL; > + std::vector symbols; > + unsigned long count = 0; > + PyObject *symtab_list = NULL; > + PyObject *minisyms_p_obj = NULL; > + int minisyms_p = 0; > + unsigned int throttle = 0; > + static const char *keywords[] = {"regex","minisyms", "throttle", "symtabs", NULL}; Nit: line too long and missing space. > + symtab_list_type symtab_paths; > + > + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!IO", keywords, > + ®ex, &PyBool_Type, > + &minisyms_p_obj, &throttle, > + &symtab_list)) > + return NULL; > + > + /* Parse minisyms keyword. */ > + if (minisyms_p_obj != NULL) > + { > + int cmp = PyObject_IsTrue (minisyms_p_obj); > + if (cmp < 0) > + return NULL; > + minisyms_p = cmp; > + } > + > + /* The "symtabs" keyword is any Python iterable object that returns > + a gdb.Symtab on each iteration. If specified, iterate through > + the provided gdb.Symtabs and extract their full path. As > + python_string_to_target_string returns a > + gdb::unique_xmalloc_ptr and a vector containing these types > + cannot be coerced to a const char **p[] via the vector.data call, > + release the value from the unique_xmalloc_ptr and place it in a > + simple type symtab_list_type (which holds the vector and a > + destructor that frees the contents of the allocated strings. */ > + if (symtab_list != NULL) > + { > + gdbpy_ref<> iter (PyObject_GetIter (symtab_list)); > + > + if (iter == NULL) > + return NULL; > + > + while (true) > + { > + gdbpy_ref<> next (PyIter_Next (iter.get ())); > + > + if (next == NULL) > + { > + if (PyErr_Occurred ()) > + return NULL; > + break; > + } > + > + gdbpy_ref<> obj_name (PyObject_GetAttrString (next.get (), > + "filename")); > + > + if (obj_name == NULL) > + return NULL; > + > + /* Is the object file still valid? */ > + if (obj_name == Py_None) > + continue; > + > + gdb::unique_xmalloc_ptr filename = > + python_string_to_target_string (obj_name.get ()); > + > + if (filename == NULL) > + return NULL; > + > + /* Make sure there is a definite place to store the value of > + s before it is released. */ > + symtab_paths.vec.push_back (nullptr); > + symtab_paths.vec.back () = filename.release (); > + } > + } > + > + if (symtab_list) > + { > + const char **files = symtab_paths.vec.data (); > + > + symbols = search_symbols (regex, FUNCTIONS_DOMAIN, > + symtab_paths.vec.size (), files); > + } > + else > + symbols = search_symbols (regex, FUNCTIONS_DOMAIN, 0, NULL); > + > + /* Count the number of symbols (both symbols and optionally mini > + symbols) so we can correctly size the tuple. */ > + for (const symbol_search &p : symbols) > + { > + /* Mini symbols included? */ > + if (minisyms_p) > + { > + if (p.msymbol.minsym != NULL) > + count++; > + } Would it be easy to pass the minisyms_p flag to search_symbols, so that we don't need to search in the minsym tables if we don't even care about them? > + > + if (p.symbol != NULL) > + count++; > + } > + > + /* Check throttle bounds and exit if in excess. */ > + if (throttle != 0 && count > throttle) > + { > + PyErr_SetString (PyExc_RuntimeError, > + _("Number of breakpoints exceeds throttled maximum.")); > + return NULL; > + } > + > + gdbpy_ref<> return_tuple (PyTuple_New (count)); > + > + if (return_tuple == NULL) > + return NULL; How do you decide if this function should return a tuple or a list? Instinctively I would have returned a list, but I can't really explain why. > + > + count = 0; > + > + /* Construct full path names for symbols and call the Python > + breakpoint constructor on the resulting names. Be tolerant of > + individual breakpoint failures. */ > + for (const symbol_search &p : symbols) > + { > + std::string symbol_name; > + > + /* Skipping mini-symbols? */ > + if (minisyms_p == 0) > + if (p.msymbol.minsym != NULL) > + continue; > + > + if (p.msymbol.minsym == NULL) > + { > + struct symtab *symtab = symbol_symtab (p.symbol); > + const char *fullname = symtab_to_fullname (symtab); > + > + symbol_name = fullname; > + symbol_name += ":"; > + symbol_name += SYMBOL_LINKAGE_NAME (p.symbol); > + } > + else > + symbol_name = MSYMBOL_LINKAGE_NAME (p.msymbol.minsym); > + > + gdbpy_ref<> argList (Py_BuildValue("(s)", symbol_name.c_str ())); > + gdbpy_ref<> obj (PyObject_CallObject ((PyObject *) > + &breakpoint_object_type, > + argList.get ())); > + > + /* Tolerate individual breakpoint failures. */ > + if (obj == NULL) > + gdbpy_print_stack (); > + else > + { > + PyTuple_SET_ITEM (return_tuple.get (), count, obj.get ()); The Python doc says that SET_ITEM steals a reference to obj. Isn't it a problem, because gdbpy_ref also keeps the reference? > + count++; > + } > + } Hmm maybe this is a reason to use a list? If a breakpoint fails to be created, the tuple will not be filled completely. What happens to tuple elements that were not set? With the list, you can simply PyList_Append. > + return return_tuple.release (); > +} > + > /* A Python function which is a wrapper for decode_line_1. */ > > static PyObject * > @@ -1912,7 +2097,9 @@ Return the name of the current target charset." }, > { "target_wide_charset", gdbpy_target_wide_charset, METH_NOARGS, > "target_wide_charset () -> string.\n\ > Return the name of the current target wide charset." }, > - > + { "rbreak", (PyCFunction) gdbpy_rbreak, METH_VARARGS | METH_KEYWORDS, > + "rbreak (Regex) -> Tuple.\n\ > +Return a Tuple containing gdb.Breakpoint objects that match the given Regex." }, > { "string_to_argv", gdbpy_string_to_argv, METH_VARARGS, > "string_to_argv (String) -> Array.\n\ > Parse String and return an argv-like array.\n\ > diff --git a/gdb/testsuite/gdb.python/py-rbreak-func2.c b/gdb/testsuite/gdb.python/py-rbreak-func2.c > new file mode 100644 > index 0000000000..1de8bfd5b2 > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-rbreak-func2.c > @@ -0,0 +1,31 @@ > +/* 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 . */ > + > +int efunc1 () > +{ > + return 1; > +} > + > +int efunc2 () > +{ > + return 2; > +} > + > +int efunc3 () > +{ > + return 3; > +} > diff --git a/gdb/testsuite/gdb.python/py-rbreak.c b/gdb/testsuite/gdb.python/py-rbreak.c > new file mode 100644 > index 0000000000..287aba6c03 > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-rbreak.c > @@ -0,0 +1,62 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2013-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 . */ > + > +int func1 () As for GDB code, put the return type on its own line. > +{ > + return 1; > +} > + > +int func2 () > +{ > + return 2; > +} > + > +int func3 () > +{ > + return 3; > +} > + > +int func4 () > +{ > + return 4; > +} > + > +int func5 () > +{ > + return 5; > +} > + > +void func6 () > +{ > + return; > +} > + > +void outside_scope () > +{ > + return; > +} > + > +int main() > +{ > + func1 (); /* Break func1. */ > + func2 (); > + func3 (); > + func4 (); > + func5 (); > + func6 (); > + outside_scope (); > +} > diff --git a/gdb/testsuite/gdb.python/py-rbreak.exp b/gdb/testsuite/gdb.python/py-rbreak.exp > new file mode 100644 > index 0000000000..9385aeae08 > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-rbreak.exp > @@ -0,0 +1,61 @@ > +# Copyright (C) 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 file is part of the GDB testsuite. It tests the mechanism > +# exposing values to Python. > + > +load_lib gdb-python.exp > + > +standard_testfile py-rbreak.c py-rbreak-func2.c > + > +if {[prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } { > + return 1 > +} > + > +# Skip all tests if Python scripting is not enabled. > +if { [skip_python_tests] } { continue } > + > +if ![runto_main] then { > + fail "can't run to main" > + return 0 > +} > + > +gdb_py_test_silent_cmd "py sl = gdb.rbreak(\"\",minisyms=False)" \ > + "Get all function breakpoints" 0 > +gdb_test "py print(len(sl))" "11" \ > + "Check number of returned breakpoints is 11" > +gdb_py_test_silent_cmd "py sl = gdb.rbreak(\"main\.\*\",minisyms=False)" \ > + "Get main function breakpoint" 0 > +gdb_test "py print(len(sl))" "1" \ > + "Check number of returned breakpoints is 1" > +gdb_py_test_silent_cmd "py sl = gdb.rbreak(\"func\.\*\",minisyms=False,throttle=10)" \ > + "Get functions matching func.*" 0 > +gdb_test "py print(len(sl))" "9" \ > + "Check number of returned breakpoints is 9" > +gdb_test "py gdb.rbreak(\"func\.\*\",minisyms=False,throttle=1)" \ > + "Number of breakpoints exceeds throttled maximum.*" \ > + "Check throttle errors on too many breakpoints." > +gdb_py_test_silent_cmd "py sl = gdb.rbreak(\"func1\",minisyms=True)" \ > + "Including mini symbols, get functions matching func.*" 0 > +gdb_test "py print(len(sl))" "2" \ > + "Check number of returned breakpoints is 2" > +gdb_py_test_silent_cmd "python sym = gdb.lookup_symbol(\"efunc1\")" \ > + "Find a symbol in objfile" 1 > +gdb_py_test_silent_cmd "python symtab = sym\[0\].symtab" \ > + "Get backing symbol table" 1 > +gdb_py_test_silent_cmd "py sl = gdb.rbreak(\"func\.\*\",minisyms=False,throttle=10,symtabs=\[symtab\])" \ > + "Get functions matching func.* in one symtab only." 0 > +gdb_test "py print(len(sl))" "3" \ > + "Check number of returned breakpoints is 3" > I can't find a reference, but I think we want test names to start with a lower case letter and not end with a dot. I'll see if we can add this to the testcase cookbook wiki page. Simon