From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6831 invoked by alias); 16 Jun 2010 13:51:50 -0000 Received: (qmail 6751 invoked by uid 22791); 16 Jun 2010 13:51:38 -0000 X-SWARE-Spam-Status: No, hits=-0.8 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,KAM_STOCKGEN,RCVD_IN_DNSWL_NONE,TW_CG,TW_CP,TW_EG,TW_VC X-Spam-Check-By: sourceware.org Received: from mail-pv0-f169.google.com (HELO mail-pv0-f169.google.com) (74.125.83.169) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 16 Jun 2010 13:51:27 +0000 Received: by pvg6 with SMTP id 6so1720563pvg.0 for ; Wed, 16 Jun 2010 06:51:25 -0700 (PDT) Received: by 10.143.20.33 with SMTP id x33mr6000609wfi.116.1276696285105; Wed, 16 Jun 2010 06:51:25 -0700 (PDT) MIME-Version: 1.0 Received: by 10.143.33.14 with HTTP; Wed, 16 Jun 2010 06:51:05 -0700 (PDT) In-Reply-To: References: <4C181DF2.7030604@vmware.com> From: Hui Zhu Date: Wed, 16 Jun 2010 13:51:00 -0000 Message-ID: Subject: Re: [PATCH] record.c: make prec can save the execution log to a pic file To: Michael Snyder Cc: gdb-patches ml Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes 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 X-SW-Source: 2010-06/txt/msg00362.txt.bz2 On Wed, Jun 16, 2010 at 12:46, Hui Zhu wrote: > On Wed, Jun 16, 2010 at 08:42, Michael Snyder wrote: >> Hui Zhu wrote: >>> >>> Hi guys, >>> >>> Before you read my introduce about this feature, please see the pic >>> file in http://www.tuhigh.com/photo/p/1600958 >>> This is a inferior execute log pic file. =A0The [BEGIN] and [END] is the >>> begin and the end this record. =A0The red line means call a function. >>> The blue line means function return. =A0The black line means simple >>> execute. >>> This pic is convented from vcg file to jpg file by graph-easy >>> (http://search.cpan.org/~tels/Graph-Easy/bin/graph-easy) >>> To see the vcg file directly. =A0I suggest you to use vcgviewer >>> (http://code.google.com/p/vcgviewer/). >> >> You really want to have gdb generate a graphics file? >> >> Seems like you could offload this task to a post-processor program, >> if you just save the record log file. =A0Then you could do anything >> you wanted to with the data, without having to add complexity and >> user commands to gdb. > > It need a lot of frame message that get from gdb. =A0I don't think do it > with myself is very easy. > > And vcg file is very speical. It's a text file. > > > Thanks, > Hui And another issue is: "record save" cannot work OK with some target, because it need this target support gcore. But "record pic" doesn't have this limit. It can work OK with "target remote" that "record save" cannot work with it. Thanks, Hui > >> >>> >>> This patch add some new commands: >>> record pic >>> Save the execution log to a vcg file. >>> >>> set record pic type line/function >>> Set the type of record pic command saved file. >>> When LINE, show each line of the inferior. >>> When FUNCTION, just show the each function. >>> >>> set record hide-nofunction on/off >>> Set whether record pic command hide the node that don't have function >>> name. >>> Default is ON. >>> When ON, record pic command will hide the node that don't have function >>> name. >>> When OFF, record pic command will show the node that don't have function >>> name. >>> >>> set record hide-nosource on/off >>> Set whether record pic command hide the node that don't have source >>> message. >>> Default is ON. >>> When ON, record pic command will hide the node that don't have function >>> name. >>> When OFF, record pic command will show the node that don't have function >>> name. >>> >>> set record hide-same on/off >>> Set whether record pic command hide the node that was shown in before. >>> Default is ON. >>> When ON, record pic command will hide the node that was shown in before. >>> It will show the execute count number of this line in format \"c:number= \". >>> When OFF, record pic command will show the node that was shown in befor= e. >>> It will show the instruction number in format \"i:number\" that >>> \"record goto\" support. >>> >>> If this patch get approved. =A0I will post patch for doc and NEWS. >>> >>> Thanks, >>> Hui >>> >>> 2010-06-16 =A0Hui Zhu =A0 >>> >>> =A0 =A0 =A0 =A0* record.c (set_record_pic_cmdlist, >>> =A0 =A0 =A0 =A0show_record_pic_cmdlist): New variables. >>> =A0 =A0 =A0 =A0(set_record_pic_command, >>> =A0 =A0 =A0 =A0show_record_pic_command): New functions. >>> =A0 =A0 =A0 =A0(record_pic_function, record_pic_line, record_pic_enum, >>> =A0 =A0 =A0 =A0set_record_pic_type, record_pic_hide_nofunction, >>> =A0 =A0 =A0 =A0record_pic_hide_nosource, record_pic_hide_same): New var= iables. >>> =A0 =A0 =A0 =A0(record_pic_fputs): New function. >>> =A0 =A0 =A0 =A0(node_list, edge_list): New struct. >>> =A0 =A0 =A0 =A0(node_list, edge_list): New variables. >>> =A0 =A0 =A0 =A0(record_pic_cleanups, record_pic_node, >>> =A0 =A0 =A0 =A0record_pic_edge, cmd_record_pic): New functions. >>> =A0 =A0 =A0 =A0(_initialize_record): Add new commands for record pic. >>> >>> >>> --- >>> =A0record.c | =A0537 >>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >>> =A01 file changed, 537 insertions(+) >>> >>> --- a/record.c >>> +++ b/record.c >>> @@ -2545,6 +2545,487 @@ cmd_record_save (char *args, int from_tt >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 recfilename); >>> =A0} >>> >>> +/* For "record pic" command. =A0*/ >>> + >>> +static struct cmd_list_element *set_record_pic_cmdlist, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *show_rec= ord_pic_cmdlist; >>> + >>> +static void >>> +set_record_pic_command (char *args, int from_tty) >>> +{ >>> + =A0printf_unfiltered (_("\ >>> +\"set record pic\" must be followed by an apporpriate subcommand.\n")); >>> + =A0help_list (set_record_cmdlist, "set record pic ", all_commands, >>> gdb_stdout); >>> +} >>> + >>> +static void >>> +show_record_pic_command (char *args, int from_tty) >>> +{ >>> + =A0cmd_show_list (show_record_pic_cmdlist, from_tty, ""); >>> +} >>> + >>> +static const char record_pic_function[] =3D "function"; >>> +static const char record_pic_line[] =3D "line"; >>> +static const char *record_pic_enum[] =3D >>> +{ >>> + =A0record_pic_function, >>> + =A0record_pic_line, >>> + =A0NULL, >>> +}; >>> +static const char *set_record_pic_type =3D record_pic_line; >>> + >>> +static int record_pic_hide_nofunction =3D 1; >>> +static int record_pic_hide_nosource =3D 1; >>> +static int =A0record_pic_hide_same =3D 1; >>> + >>> +static void >>> +record_pic_fputs (FILE *fp, const char *buf) >>> +{ >>> + =A0if (fputs (buf, fp) =3D=3D EOF) >>> + =A0 =A0error (_("Write to file error.")); >>> +} >>> + >>> +struct node_list >>> +{ >>> + =A0struct node_list *next; >>> + =A0int count; >>> + =A0CORE_ADDR addr; >>> + =A0int showall; >>> + =A0struct symtab *symtab; >>> + =A0int line; >>> + =A0struct minimal_symbol *function; >>> +}; >>> +struct edge_list >>> +{ >>> + =A0struct edge_list *next; >>> + =A0int count; >>> + =A0struct node_list *s; >>> + =A0struct node_list *t; >>> + =A0int frame_diff; >>> + =A0int is_return; >>> +}; >>> +struct node_list *node_list =3D NULL; >>> +struct edge_list *edge_list =3D NULL; >>> + >>> +static void >>> +record_pic_cleanups (void *data) >>> +{ >>> + =A0FILE *fp =3D data; >>> + =A0struct node_list *nl, *nl2; >>> + =A0struct edge_list *el, *el2; >>> + >>> + =A0nl =3D node_list; >>> + =A0while (nl) >>> + =A0 =A0{ >>> + =A0 =A0 =A0nl2 =3D nl; >>> + =A0 =A0 =A0nl =3D nl->next; >>> + =A0 =A0 =A0xfree (nl2); >>> + =A0 =A0} >>> + =A0node_list =3D NULL; >>> + >>> + =A0el =3D edge_list; >>> + =A0while (el) >>> + =A0 =A0{ >>> + =A0 =A0 =A0el2 =3D el; >>> + =A0 =A0 =A0el =3D el->next; >>> + =A0 =A0 =A0xfree (el2); >>> + =A0 =A0} >>> + =A0edge_list =3D NULL; >>> + >>> + =A0fclose (fp); >>> +} >>> + >>> +static void >>> +record_pic_node (char *buf, int buf_max, struct gdbarch *gdbarch, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 const char *type, struct node_list *n= lp) >>> +{ >>> + =A0if (type =3D=3D record_pic_function) >>> + =A0 =A0{ >>> + =A0 =A0 =A0snprintf (buf, buf_max, "%s %s %s", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 (nlp->symtab) ? nlp->symtab->filename : "= ", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(nlp->function) ? SYMBOL_LINKAGE_NAME = (nlp->function) : >>> "", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(!nlp->function) ? paddress (gdbarch, = nlp->addr) : ""); >>> + =A0 =A0} >>> + =A0else >>> + =A0 =A0{ >>> + =A0 =A0 =A0if (nlp->showall) >>> + =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 snprintf (buf, buf_max, "%s:%d %s %s", nlp->symtab->f= ilename, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nlp->line, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(nlp->function) ? SYMBOL_LINKA= GE_NAME (nlp->function) >>> : "", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0paddress (gdbarch, nlp->addr)); >>> + =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0if (nlp->symtab) >>> + =A0 =A0 =A0 =A0 =A0 snprintf (buf, buf_max, "%s %d %s", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(nlp->function) ? SYMBOL_L= INKAGE_NAME >>> (nlp->function) : "", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nlp->line, paddress (gdbar= ch, nlp->addr)); >>> + =A0 =A0 =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0 =A0 =A0snprintf (buf, buf_max, "%s %s", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(nlp->function) ? SYMBOL_L= INKAGE_NAME >>> (nlp->function) : "", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0paddress (gdbarch, nlp->ad= dr)); >>> + =A0 =A0 =A0 =A0} >>> + =A0 =A0} >>> +} >>> + >>> +static void >>> +record_pic_edge (char *buf, int buf_max, struct edge_list *elp, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0char *node, char *prev_node) >>> +{ >>> + =A0if (elp->frame_diff) >>> + =A0 =A0{ >>> + =A0 =A0 =A0if (elp->is_return) >>> + =A0 =A0 =A0 =A0snprintf (buf, buf_max, "edge: {color:blue sourcename:= \"%s\" " >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"targe= tname: \"%s\"", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 prev_node, node); >>> + =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0snprintf (buf, buf_max, "edge: {color:red sourcename: = \"%s\" " >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"targe= tname: \"%s\"", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 prev_node, node); >>> + =A0 =A0} >>> + =A0else >>> + =A0 =A0snprintf (buf, buf_max, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0"nearedge: {sourcename: \"%s\" targetname:= \"%s\"", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0prev_node, node); >>> +} >>> + >>> +/* Save the execution log to a vcg file. =A0*/ >>> + >>> +static void >>> +cmd_record_pic (char *args, int from_tty) >>> +{ >>> + =A0char *recfilename, recfilename_buffer[40]; >>> + =A0FILE *fp; >>> + =A0struct cleanup *old_cleanups, *set_cleanups; >>> + =A0struct regcache *regcache; >>> + =A0struct gdbarch *gdbarch; >>> + =A0struct record_entry *cur_record_list; >>> + =A0char prev_node[256], line[256]; >>> + =A0CORE_ADDR prev_addr; >>> + =A0struct frame_id fi, caller_fi, prev_fi, prev_caller_fi; >>> + =A0struct edge_list *edge_list_tail =3D NULL; >>> + =A0struct node_list *node_list_tail =3D NULL; >>> + =A0struct symtab_and_line sal, prev_sal; >>> + =A0struct node_list *prev_nlp; >>> + =A0struct node_list prev_nlp_real; >>> + >>> + =A0/* Check if record target is running. =A0*/ >>> + =A0if (current_target.to_stratum !=3D record_stratum) >>> + =A0 =A0error (_("This command can only be used with target 'record' \ >>> +or target 'record-core'.")); >>> + >>> + =A0if (args && *args) >>> + =A0 =A0recfilename =3D args; >>> + =A0else >>> + =A0 =A0{ >>> + =A0 =A0 =A0/* Default recfile name is "gdb_record_PID.vcg". =A0*/ >>> + =A0 =A0 =A0snprintf (recfilename_buffer, sizeof (recfilename_buffer), >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"gdb_record_%d.vcg", PIDGET (inferior_= ptid)); >>> + =A0 =A0 =A0recfilename =3D recfilename_buffer; >>> + =A0 =A0} >>> + >>> + =A0/* Open the output file. =A0*/ >>> + =A0fp =3D fopen (recfilename, "wb"); >>> + =A0if (!fp) >>> + =A0 =A0error (_("Unable to open file '%s'"), recfilename); >>> + >>> + =A0old_cleanups =3D make_cleanup (record_pic_cleanups, fp); >>> + >>> + =A0/* Save the current record entry to "cur_record_list". =A0*/ >>> + =A0cur_record_list =3D record_list; >>> + >>> + =A0/* Get the values of regcache and gdbarch. =A0*/ >>> + =A0regcache =3D get_current_regcache (); >>> + =A0gdbarch =3D get_regcache_arch (regcache); >>> + >>> + =A0/* Disable the GDB operation record. =A0*/ >>> + =A0set_cleanups =3D record_gdb_operation_disable_set (); >>> + >>> + =A0/* Reverse execute to the begin of record list. =A0*/ >>> + =A0while (1) >>> + =A0 =A0{ >>> + =A0 =A0 =A0/* Check for beginning and end of log. =A0*/ >>> + =A0 =A0 =A0if (record_list =3D=3D &record_first) >>> + =A0 =A0 =A0 =A0break; >>> + >>> + =A0 =A0 =A0record_exec_insn (regcache, gdbarch, record_list); >>> + >>> + =A0 =A0 =A0if (record_list->prev) >>> + =A0 =A0 =A0 =A0record_list =3D record_list->prev; >>> + =A0 =A0} >>> + >>> + =A0/* Write out the record log. =A0*/ >>> + =A0/* Write the head. =A0*/ >>> + =A0record_pic_fputs (fp, "graph: {title: \"GDB process record\"\n"); >>> + >>> + =A0/* Write the first node. =A0*/ >>> + =A0record_pic_fputs (fp, "node: {title: \"[BEGIN]\"}\n"); >>> + >>> + =A0/* Initialization. =A0*/ >>> + =A0snprintf (prev_node, 256, "[BEGIN]"); >>> + =A0prev_fi =3D null_frame_id; >>> + =A0prev_caller_fi =3D null_frame_id; >>> + =A0prev_addr =3D 0; >>> + =A0prev_sal.symtab =3D NULL; >>> + =A0prev_nlp_real.addr =3D 0; >>> + =A0prev_nlp =3D &prev_nlp_real; >>> + >>> + =A0/* Save the entries to fp and forward execute to the end of >>> + =A0 =A0 record list. =A0*/ >>> + =A0record_list =3D &record_first; >>> + =A0while (1) >>> + =A0 =A0{ >>> + =A0 =A0 =A0if (record_list->type =3D=3D record_end) >>> + =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0int frame_diff =3D 0; >>> + =A0 =A0 =A0 =A0 =A0CORE_ADDR addr =3D regcache_read_pc (regcache); >>> + >>> + =A0 =A0 =A0 =A0 =A0/* Check if the ADDR is stil in the same line with= the >>> + =A0 =A0 =A0 =A0 =A0 =A0 prev cycle. =A0*/ >>> + =A0 =A0 =A0 =A0 =A0if (prev_sal.symtab >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0&& addr >=3D prev_sal.pc && addr < prev_sa= l.end) >>> + =A0 =A0 =A0 =A0 =A0 =A0goto exec; >>> + =A0 =A0 =A0 =A0 =A0sal =3D find_pc_line (addr, 0); >>> + >>> + =A0 =A0 =A0 =A0 =A0if (record_pic_hide_nosource && !sal.symtab) >>> + =A0 =A0 =A0 =A0 =A0 =A0goto exec; >>> + >>> + =A0 =A0 =A0 =A0 =A0/* Check if the inferior is in same frame with pre= v cycle. >>> + =A0 =A0 =A0 =A0 =A0 =A0 Check both the current fi and caller fi becau= se the last >>> + =A0 =A0 =A0 =A0 =A0 =A0 addr of function is different with current fu= nction. =A0*/ >>> + =A0 =A0 =A0 =A0 =A0reinit_frame_cache (); >>> + =A0 =A0 =A0 =A0 =A0fi =3D get_frame_id (get_current_frame ()); >>> + =A0 =A0 =A0 =A0 =A0caller_fi =3D frame_unwind_caller_id (get_current_= frame ()); >>> + =A0 =A0 =A0 =A0 =A0if (!frame_id_eq (prev_fi, fi) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0&& !frame_id_eq (prev_caller_fi, caller_fi= )) >>> + =A0 =A0 =A0 =A0 =A0 =A0frame_diff =3D 1; >>> + >>> + =A0 =A0 =A0 =A0 =A0if (set_record_pic_type =3D=3D record_pic_line || = frame_diff) >>> + =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0int is_return =3D 0; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0struct node_list *nlp =3D NULL; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0struct edge_list *elp =3D NULL; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0char node[256]; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0struct minimal_symbol *function; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 /* Get the node addr. =A0*/ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0if (set_record_pic_type =3D=3D record_pic_= function) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Get the start addr of function.= =A0*/ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0addr =3D get_pc_function_start (ad= dr); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (addr =3D=3D 0) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (record_pic_hide_nofunc= tion) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto exec; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0addr =3D regcache_read_pc = (regcache); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Get the start addr of line. =A0= */ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (sal.symtab) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0addr =3D sal.pc; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0function =3D lookup_minimal_symbol_by_pc (= addr); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0if (!function && record_pic_hide_nofunctio= n) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto exec; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0if (frame_id_eq (fi, prev_caller_fi)) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0is_return =3D 1; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0if (record_pic_hide_same) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Check if addr in node_list. =A0= */ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for (nlp =3D node_list; nlp; nlp = =3D nlp->next) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (nlp->addr =3D=3D addr) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!is_return >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 || set_record= _pic_type !=3D >>> record_pic_function) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nlp->count ++; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Check if prev_addr and addr in = edge_list. =A0*/ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (nlp) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 { >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for (elp =3D edge_list; el= p; elp =3D elp->next) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (elp->s->addr = =3D=3D prev_addr && >>> elp->t->addr =3D=3D addr) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0elp->count= ++; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0if (!nlp) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct node_list nl; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nl.addr =3D addr; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (frame_diff && sal.symtab) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nl.showall =3D 1; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nl.showall =3D 0; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nl.symtab =3D sal.symtab; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nl.line =3D sal.line; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nl.function =3D function; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (record_pic_hide_same) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nlp =3D xmalloc (sizeof (s= truct node_list)); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*nlp =3D nl; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nlp->count =3D 1; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Add node to node_list. = =A0*/ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0nlp->next =3D NULL; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (node_list_tail) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0node_list_tail->next = =3D nlp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (node_list =3D=3D NULL) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 node_list =3D nlp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0node_list_tail =3D nlp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Draw the node. =A0*/ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0record_pic_node (node, 256= , gdbarch, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 set_record_pic_type, &nl); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 snprintf (line, 256, "%s i:%s= ", node, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pulongest= (record_list->u.end.insn_num)); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 strcpy (node, line); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0snprintf (line, 256, "node= : {title: \"%s\"}\n", >>> node); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0record_pic_fputs (fp, line= ); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0if (!elp) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct edge_list el; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0el.is_return =3D is_return; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0el.frame_diff =3D frame_diff; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (record_pic_hide_same) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0elp =3D xmalloc (sizeof (s= truct edge_list)); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*elp =3D el; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 elp->s =3D prev_nlp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0elp->t =3D nlp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0elp->count =3D 1; >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Add edge to edge_list. = =A0*/ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0elp->next =3D NULL; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (edge_list_tail) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0edge_list_tail->next = =3D elp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (edge_list =3D=3D NULL) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 edge_list =3D elp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0edge_list_tail =3D elp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Draw the edge. =A0*/ >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0record_pic_edge (line, 256= , &el, node, prev_node); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0record_pic_fputs (fp, line= ); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 record_pic_fputs (fp, " }\n"); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >>> + >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0if (record_pic_hide_same) >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prev_nlp =3D nlp; >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0snprintf (prev_node, 256, "%s", node); >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0prev_addr =3D addr; >>> + =A0 =A0 =A0 =A0 =A0 =A0} >>> + >>> + =A0 =A0 =A0 =A0 =A0prev_sal =3D sal; >>> + =A0 =A0 =A0 =A0 =A0prev_fi =3D fi; >>> + =A0 =A0 =A0 =A0 =A0prev_caller_fi =3D caller_fi; >>> + =A0 =A0 =A0 =A0} >>> + >>> +exec: >>> + =A0 =A0 =A0/* Execute entry. =A0*/ >>> + =A0 =A0 =A0record_exec_insn (regcache, gdbarch, record_list); >>> + >>> + =A0 =A0 =A0if (record_list->next) >>> + =A0 =A0 =A0 =A0record_list =3D record_list->next; >>> + =A0 =A0 =A0else >>> + =A0 =A0 =A0 =A0break; >>> + =A0 =A0} >>> + >>> + =A0if (record_pic_hide_same) >>> + =A0 =A0{ >>> + =A0 =A0 =A0struct node_list *nlp =3D NULL; >>> + =A0 =A0 =A0struct edge_list *elp =3D NULL; >>> + =A0 =A0 =A0char node[256]; >>> + >>> + =A0 =A0 =A0for (nlp =3D node_list; nlp; nlp =3D nlp->next) >>> + =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0/* Draw the node. =A0*/ >>> + =A0 =A0 =A0 =A0 =A0record_pic_node (node, 256, gdbarch, set_record_pi= c_type, nlp); >>> + =A0 =A0 =A0 =A0 =A0snprintf (line, 256, "node: {title: \"%s c:%d\"}\n= ", node, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 nlp->count); >>> + =A0 =A0 =A0 =A0 =A0record_pic_fputs (fp, line); >>> + =A0 =A0 =A0 } >>> + >>> + =A0 =A0 =A0record_pic_node (node, 256, gdbarch, set_record_pic_type, >>> edge_list->t); >>> + =A0 =A0 =A0snprintf (line, 256, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 "nearedge: {color:red sourcename: \"[BEGI= N]\" targetname: >>> \"%s c:%d\"}\n", >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 node, edge_list->count); >>> + =A0 =A0 =A0record_pic_fputs (fp, line); >>> + =A0 =A0 =A0for (elp =3D edge_list->next; elp; elp =3D elp->next) >>> + =A0 =A0 =A0 =A0{ >>> + =A0 =A0 =A0 =A0 =A0/* Draw the edge. =A0*/ >>> + =A0 =A0 =A0 =A0 record_pic_node (prev_node, 256, gdbarch, set_record_= pic_type, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0elp->s); >>> + =A0 =A0 =A0 =A0 snprintf (line, 256, "%s c:%d", prev_node, elp->s->co= unt); >>> + =A0 =A0 =A0 =A0 strcpy (prev_node, line); >>> + =A0 =A0 =A0 =A0 record_pic_node (node, 256, gdbarch, set_record_pic_t= ype, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0elp->t); >>> + =A0 =A0 =A0 =A0 snprintf (line, 256, "%s c:%d", node, elp->t->count); >>> + =A0 =A0 =A0 =A0 strcpy (node, line); >>> + =A0 =A0 =A0 =A0 =A0record_pic_edge (line, 256, elp, node, prev_node); >>> + =A0 =A0 =A0 =A0 =A0record_pic_fputs (fp, line); >>> + =A0 =A0 =A0 =A0 =A0snprintf (line, 256, " label: \"c:%d\"}\n", elp->c= ount); >>> + =A0 =A0 =A0 =A0 record_pic_fputs (fp, line); >>> + =A0 =A0 =A0 =A0} >>> + =A0 =A0} >>> + >>> + =A0/* Write the last node. =A0*/ >>> + =A0record_pic_fputs (fp, "node: {title: \"[END]\"}\n"); >>> + =A0snprintf (line, 256, >>> + =A0 =A0 =A0 =A0 =A0 "nearedge: {color:red sourcename: \"%s\" targetna= me: \"[END]\" >>> }\n", >>> + =A0 =A0 =A0 =A0 =A0 prev_node); >>> + =A0record_pic_fputs (fp, line); >>> + >>> + =A0/* Write the tail. =A0*/ >>> + =A0record_pic_fputs (fp, "}\n"); >>> + >>> + =A0/* Reverse execute to cur_record_list. =A0*/ >>> + =A0while (1) >>> + =A0 =A0{ >>> + =A0 =A0 =A0/* Check for beginning and end of log. =A0*/ >>> + =A0 =A0 =A0if (record_list =3D=3D cur_record_list) >>> + =A0 =A0 =A0 =A0break; >>> + >>> + =A0 =A0 =A0record_exec_insn (regcache, gdbarch, record_list); >>> + >>> + =A0 =A0 =A0if (record_list->prev) >>> + =A0 =A0 =A0 =A0record_list =3D record_list->prev; >>> + =A0 =A0} >>> + >>> + =A0do_cleanups (set_cleanups); >>> + =A0do_cleanups (old_cleanups); >>> + >>> + =A0/* Succeeded. =A0*/ >>> + =A0printf_filtered (_("Saved file %s with execution log.\n"), >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0recfilename); >>> +} >>> + >>> =A0/* record_goto_insn -- rewind the record log (forward or backward, >>> =A0 =A0depending on DIR) to the given entry, changing the program state >>> =A0 =A0correspondingly. =A0*/ >>> @@ -2730,4 +3211,60 @@ record/replay buffer. =A0Zero means unlimi >>> =A0Restore the program to its state at instruction number N.\n\ >>> =A0Argument is instruction number, as shown by 'info record'."), >>> =A0 =A0 =A0 =A0 =A0 &record_cmdlist); >>> + >>> + =A0/* For "record pic" command. =A0*/ >>> + =A0c =3D add_cmd ("pic", class_obscure, cmd_record_pic, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0_("Save the execution log to a vcg file.\n\ >>> +Argument is optional filename.\n\ >>> +Default filename is 'gdb_record_.vcg'."), >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0&record_cmdlist); >>> + =A0set_cmd_completer (c, filename_completer); >>> + =A0add_prefix_cmd ("pic", class_support, set_record_pic_command, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 _("Set record pic options"), &set_rec= ord_pic_cmdlist, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "set record pic ", 0, &set_record_cmd= list); >>> + =A0add_prefix_cmd ("pic", class_support, show_record_pic_command, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 _("Show record pic options"), &show_r= ecord_pic_cmdlist, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "show record pic ", 0, &show_record_c= mdlist); >>> + =A0add_setshow_enum_cmd ("type", no_class, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 record_pic_enum, &set_rec= ord_pic_type, _("\ >>> +Set the type of record pic command saved file."), _("\ >>> +Show the type of record pic command saved file."), _("\ >>> +When LINE, show each line of the inferior.\n\ >>> +When FUNCTION, just show the each function."), >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 NULL, NULL, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &set_record_pic_cmdlist, >>> &show_record_pic_cmdlist); >>> + =A0add_setshow_boolean_cmd ("hide-nofunction", no_class, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&record_pic_hide_n= ofunction, _("\ >>> +Set whether record pic command hide the node that don't have function >>> name."), _("\ >>> +Show whether record pic command hide the node that don't have >>> function name."), _("\ >>> +Default is ON.\n\ >>> +When ON, record pic command will hide the node that don't have\n\ >>> +function name.\n\ >>> +When OFF, record pic command will show the node that don't have\n\ >>> +function name."), >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0NULL, NULL, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&set_record_pic_cm= dlist, >>> &show_record_pic_cmdlist); >>> + =A0add_setshow_boolean_cmd ("hide-nosource", no_class, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&record_pic_hide_n= osource, _("\ >>> +Set whether record pic command hide the node that don't have source >>> message."), _("\ >>> +Show whether record pic command hide the node that don't have source >>> message."), _("\ >>> +Default is ON.\n\ >>> +When ON, record pic command will hide the node that don't have\n\ >>> +function name.\n\ >>> +When OFF, record pic command will show the node that don't have\n\ >>> +function name."), >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0NULL, NULL, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&set_record_pic_cm= dlist, >>> &show_record_pic_cmdlist); >>> + =A0add_setshow_boolean_cmd ("hide-same", no_class, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&record_pic_hide_s= ame, _("\ >>> +Set whether record pic command hide the node that was shown in before.= "), >>> _("\ >>> +Show whether record pic command hide the node that was shown in >>> before."), _("\ >>> +Default is ON.\n\ >>> +When ON, record pic command will hide the node that was shown in >>> before.\n\ >>> +It will show the execute count number of this line in format >>> \"c:number\".\n\ >>> +When OFF, record pic command will show the node that was shown in >>> before.\n\ >>> +It will show the instruction number in format \"i:number\"\n\ >>> +that \"record goto\" support."), >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0NULL, NULL, >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&set_record_pic_cm= dlist, >>> &show_record_pic_cmdlist); >>> =A0} >>> >> >> >