From patchwork Fri Feb 19 12:40:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 585181 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id CEE24140556 for ; Fri, 19 Feb 2016 23:40:47 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=N/PGZ9UH; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=EvJ5L5oIP/OrnPbyz twDzOPwB5xO64Ze/A/ln6+ZXWLI+aJp5P6OLXDUSoInyUcVANX3P7v6sp2BXboC8 Afy/f3KXqIF9k5OqOgiPGGvRca5Z2+9p5QY33w/zcmgVCmjN24O/V93S2dPl3P16 Nh4BgJ4Vc9jTZq5QkBhOlgo+Cg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=0eNrT7DnQDjCnf3RamdCJJW WmxY=; b=N/PGZ9UHArmcKk2uDgYr/+Zg58CeHFf3hfo+qpnVDoJbjwyH0AZ2Hyp 1LQJnj+JvsejKlKg2MkZU4FGodqkiagu1bS1eQerVyG0suYgvclnvLVlIJL3cYIW eaS7K3pCWorMt/skPK0/t9RTpsgeZirud6RfQTd9NIK+g53I/Hoc= Received: (qmail 80673 invoked by alias); 19 Feb 2016 12:40:40 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 80655 invoked by uid 89); 19 Feb 2016 12:40:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=DumpFn, dumpfn, dump-fn, usecase X-HELO: fencepost.gnu.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (208.118.235.10) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 19 Feb 2016 12:40:37 +0000 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37272) by fencepost.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1aWkMN-0005GS-KK for gcc-patches@gnu.org; Fri, 19 Feb 2016 07:40:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aWkMI-0005qZ-LA for gcc-patches@gnu.org; Fri, 19 Feb 2016 07:40:35 -0500 Received: from relay1.mentorg.com ([192.94.38.131]:45395) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aWkMI-0005qH-CP for gcc-patches@gnu.org; Fri, 19 Feb 2016 07:40:30 -0500 Received: from nat-ies.mentorg.com ([192.94.31.2] helo=SVR-IES-FEM-01.mgc.mentorg.com) by relay1.mentorg.com with esmtp id 1aWkMF-0007H9-5G from Tom_deVries@mentor.com ; Fri, 19 Feb 2016 04:40:27 -0800 Received: from [127.0.0.1] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.3.224.2; Fri, 19 Feb 2016 12:40:25 +0000 Subject: Re: [PATCH] Add debug_function_to_file To: Richard Biener References: <56C46A70.4070605@mentor.com> <56C5D52E.9040302@mentor.com> <56C5E0A9.1040900@mentor.com> <56C663BC.6000905@mentor.com> CC: "gcc-patches@gnu.org" , David Malcolm From: Tom de Vries Message-ID: <56C70D2F.4040907@mentor.com> Date: Fri, 19 Feb 2016 13:40:15 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 In-Reply-To: X-detected-operating-system: by eggs.gnu.org: Windows NT kernel [generic] [fuzzy] X-Received-From: 192.94.38.131 On 19/02/16 10:44, Richard Biener wrote: > On Fri, Feb 19, 2016 at 1:37 AM, Tom de Vries wrote: >> On 18/02/16 16:27, Richard Biener wrote: >>> >>> Attached is what I have for now, it works if you call it like >>> >>> (gdb) dot-fn cfun >>> (gdb) dot-fn cfun, 1<<6 >>> >>> w/o that arg parsing;) >>> >>> I'll play with it some more tomorrow. >> >> >> This version: >> - uses arg parsing >> - adds error handling >> - uses a temp file instead of a pipe >> - uses python os.system to call dot > > I used popen It was suggested in the other thread ( https://gcc.gnu.org/ml/gcc-patches/2016-02/msg01172.html ) that there were portability issues with popen, so I tried to avoid it. Anyway, I guess it's probably best to try to minimize interaction with the inferior, if we can handle it in python instead. > specifically to allow you continue debugging while keeping the dot > process open and functional. Ah, I see. > That would be restored with adding a '&' after > the command but then we race with the file removal ... > > The following works for me though: > > # Show graph in temp file > os.system("( dot -Tx11 %s; rm %s ) &" % (filename, filename) ) > > dot_fn() > Yep, that works for me too. [ Btw, I prefer generating dot graps in pdf format. In the pdf viewer, you can search for variable names, bb numbers, etc. It's easy enough to generate the pdf file, but I'm not sure how in python we can open the pdf viewer, and wait for it to finish in a portable way. xdg-open is linux-only and doesn't seem to wait-on -finish. And pythons webbrowser.open_new does wait-on-finish in some cases, but not in others, and I don't understand the documentation well enough to know if that's going to affect this use-case. ] > ok for trunk with that change and thanks for the help! > You're welcome :) . [ I used to use python regularly (though at a basic level) about 6 years ago, but haven't used it since, so it was good to revive that skill a bit. ] I'll commit as attached, unless David has further review comments on dot-fn (or comments on dump-fn which would also apply for dot-fn). Thanks, - Tom Add dot-fn to gdbhooks.py 2016-02-18 Richard Biener * graph.c: Include dumpfile.h. (print_graph_cfg): Split into three overloads. * gdbhooks.py (dot-fn): New command. --- gcc/gdbhooks.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/graph.c | 32 ++++++++++++++++++++++---- 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py index ed72016..1212312 100644 --- a/gcc/gdbhooks.py +++ b/gcc/gdbhooks.py @@ -680,4 +680,74 @@ class DumpFn(gdb.Command): DumpFn() +class DotFn(gdb.Command): + """ + A custom command to show a gimple/rtl function control flow graph. + By default, it show the current function, but the function can also be + specified. + + Examples of use: + (gdb) dot-fn + (gdb) dot-fn cfun + (gdb) dot-fn cfun 0 + (gdb) dot-fn cfun dump_flags + """ + def __init__(self): + gdb.Command.__init__(self, 'dot-fn', gdb.COMMAND_USER) + + def invoke(self, arg, from_tty): + # Parse args, check number of args + args = gdb.string_to_argv(arg) + if len(args) > 2: + print("Too many arguments") + return + + # Set func + if len(args) >= 1: + funcname = args[0] + printfuncname = "function %s" % funcname + else: + funcname = "cfun" + printfuncname = "current function" + func = gdb.parse_and_eval(funcname) + if func == 0: + print("Could not find %s" % printfuncname) + return + func = "(struct function *)%s" % func + + # Set flags + if len(args) >= 2: + flags = gdb.parse_and_eval(args[1]) + else: + flags = 0 + + # Get temp file + f = tempfile.NamedTemporaryFile(delete=False) + filename = f.name + + # Close and reopen temp file to get C FILE* + f.close() + fp = gdb.parse_and_eval("fopen (\"%s\", \"w\")" % filename) + if fp == 0: + print("Cannot open temp file") + return + fp = "(FILE *)%u" % fp + + # Write graph to temp file + _ = gdb.parse_and_eval("start_graph_dump (%s, \"\")" % fp) + _ = gdb.parse_and_eval("print_graph_cfg (%s, %s, %u)" + % (fp, func, flags)) + _ = gdb.parse_and_eval("end_graph_dump (%s)" % fp) + + # Close temp file + ret = gdb.parse_and_eval("fclose (%s)" % fp) + if ret != 0: + print("Could not close temp file: %s" % filename) + return + + # Show graph in temp file + os.system("( dot -Tx11 \"%s\"; rm \"%s\" ) &" % (filename, filename)) + +DotFn() + print('Successfully loaded GDB hooks for GCC') diff --git a/gcc/graph.c b/gcc/graph.c index 1b28c67..dd5bc4e 100644 --- a/gcc/graph.c +++ b/gcc/graph.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "cfganal.h" #include "cfgloop.h" #include "graph.h" +#include "dumpfile.h" /* DOT files with the .dot extension are recognized as document templates by a well-known piece of word processing software out of Redmond, WA. @@ -272,14 +273,13 @@ draw_cfg_edges (pretty_printer *pp, struct function *fun) subgraphs right for GraphViz, which requires nodes to be defined before edges to cluster nodes properly. */ -void -print_graph_cfg (const char *base, struct function *fun) +void DEBUG_FUNCTION +print_graph_cfg (FILE *fp, struct function *fun) { - const char *funcname = function_name (fun); - FILE *fp = open_graph_file (base, "a"); pretty_printer graph_slim_pp; graph_slim_pp.buffer->stream = fp; pretty_printer *const pp = &graph_slim_pp; + const char *funcname = function_name (fun); pp_printf (pp, "subgraph \"cluster_%s\" {\n" "\tstyle=\"dashed\";\n" "\tcolor=\"black\";\n" @@ -289,6 +289,30 @@ print_graph_cfg (const char *base, struct function *fun) draw_cfg_edges (pp, fun); pp_printf (pp, "}\n"); pp_flush (pp); +} + +/* Overload with additional flag argument. */ + +void DEBUG_FUNCTION +print_graph_cfg (FILE *fp, struct function *fun, int flags) +{ + int saved_dump_flags = dump_flags; + dump_flags = flags; + print_graph_cfg (fp, fun); + dump_flags = saved_dump_flags; +} + + +/* Print a graphical representation of the CFG of function FUN. + First print all basic blocks. Draw all edges at the end to get + subgraphs right for GraphViz, which requires nodes to be defined + before edges to cluster nodes properly. */ + +void +print_graph_cfg (const char *base, struct function *fun) +{ + FILE *fp = open_graph_file (base, "a"); + print_graph_cfg (fp, fun); fclose (fp); }