This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] record.c: make prec can save the execution log to a pic file


On Wed, Jun 16, 2010 at 08:42, Michael Snyder <msnyder@vmware.com> 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. ?The [BEGIN] and [END] is the
>> begin and the end this record. ?The red line means call a function.
>> The blue line means function return. ?The 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. ?I 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. ?Then 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.  I don't think do it
with myself is very easy.

And vcg file is very speical. It's a text file.


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 before.
>> It will show the instruction number in format \"i:number\" that
>> \"record goto\" support.
>>
>> If this patch get approved. ?I will post patch for doc and NEWS.
>>
>> Thanks,
>> Hui
>>
>> 2010-06-16 ?Hui Zhu ?<teawater@gmail.com>
>>
>> ? ? ? ?* record.c (set_record_pic_cmdlist,
>> ? ? ? ?show_record_pic_cmdlist): New variables.
>> ? ? ? ?(set_record_pic_command,
>> ? ? ? ?show_record_pic_command): New functions.
>> ? ? ? ?(record_pic_function, record_pic_line, record_pic_enum,
>> ? ? ? ?set_record_pic_type, record_pic_hide_nofunction,
>> ? ? ? ?record_pic_hide_nosource, record_pic_hide_same): New variables.
>> ? ? ? ?(record_pic_fputs): New function.
>> ? ? ? ?(node_list, edge_list): New struct.
>> ? ? ? ?(node_list, edge_list): New variables.
>> ? ? ? ?(record_pic_cleanups, record_pic_node,
>> ? ? ? ?record_pic_edge, cmd_record_pic): New functions.
>> ? ? ? ?(_initialize_record): Add new commands for record pic.
>>
>>
>> ---
>> ?record.c | ?537
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> ?1 file changed, 537 insertions(+)
>>
>> --- a/record.c
>> +++ b/record.c
>> @@ -2545,6 +2545,487 @@ cmd_record_save (char *args, int from_tt
>> ? ? ? ? ? ? ? ? ? recfilename);
>> ?}
>>
>> +/* For "record pic" command. ?*/
>> +
>> +static struct cmd_list_element *set_record_pic_cmdlist,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *show_record_pic_cmdlist;
>> +
>> +static void
>> +set_record_pic_command (char *args, int from_tty)
>> +{
>> + ?printf_unfiltered (_("\
>> +\"set record pic\" must be followed by an apporpriate subcommand.\n"));
>> + ?help_list (set_record_cmdlist, "set record pic ", all_commands,
>> gdb_stdout);
>> +}
>> +
>> +static void
>> +show_record_pic_command (char *args, int from_tty)
>> +{
>> + ?cmd_show_list (show_record_pic_cmdlist, from_tty, "");
>> +}
>> +
>> +static const char record_pic_function[] = "function";
>> +static const char record_pic_line[] = "line";
>> +static const char *record_pic_enum[] =
>> +{
>> + ?record_pic_function,
>> + ?record_pic_line,
>> + ?NULL,
>> +};
>> +static const char *set_record_pic_type = record_pic_line;
>> +
>> +static int record_pic_hide_nofunction = 1;
>> +static int record_pic_hide_nosource = 1;
>> +static int ?record_pic_hide_same = 1;
>> +
>> +static void
>> +record_pic_fputs (FILE *fp, const char *buf)
>> +{
>> + ?if (fputs (buf, fp) == EOF)
>> + ? ?error (_("Write to file error."));
>> +}
>> +
>> +struct node_list
>> +{
>> + ?struct node_list *next;
>> + ?int count;
>> + ?CORE_ADDR addr;
>> + ?int showall;
>> + ?struct symtab *symtab;
>> + ?int line;
>> + ?struct minimal_symbol *function;
>> +};
>> +struct edge_list
>> +{
>> + ?struct edge_list *next;
>> + ?int count;
>> + ?struct node_list *s;
>> + ?struct node_list *t;
>> + ?int frame_diff;
>> + ?int is_return;
>> +};
>> +struct node_list *node_list = NULL;
>> +struct edge_list *edge_list = NULL;
>> +
>> +static void
>> +record_pic_cleanups (void *data)
>> +{
>> + ?FILE *fp = data;
>> + ?struct node_list *nl, *nl2;
>> + ?struct edge_list *el, *el2;
>> +
>> + ?nl = node_list;
>> + ?while (nl)
>> + ? ?{
>> + ? ? ?nl2 = nl;
>> + ? ? ?nl = nl->next;
>> + ? ? ?xfree (nl2);
>> + ? ?}
>> + ?node_list = NULL;
>> +
>> + ?el = edge_list;
>> + ?while (el)
>> + ? ?{
>> + ? ? ?el2 = el;
>> + ? ? ?el = el->next;
>> + ? ? ?xfree (el2);
>> + ? ?}
>> + ?edge_list = NULL;
>> +
>> + ?fclose (fp);
>> +}
>> +
>> +static void
>> +record_pic_node (char *buf, int buf_max, struct gdbarch *gdbarch,
>> + ? ? ? ? ? ? ? ? const char *type, struct node_list *nlp)
>> +{
>> + ?if (type == record_pic_function)
>> + ? ?{
>> + ? ? ?snprintf (buf, buf_max, "%s %s %s",
>> + ? ? ? ? ? ? ? (nlp->symtab) ? nlp->symtab->filename : "",
>> + ? ? ? ? ? ? ? ?(nlp->function) ? SYMBOL_LINKAGE_NAME (nlp->function) :
>> "",
>> + ? ? ? ? ? ? ? ?(!nlp->function) ? paddress (gdbarch, nlp->addr) : "");
>> + ? ?}
>> + ?else
>> + ? ?{
>> + ? ? ?if (nlp->showall)
>> + ? ? ? ?{
>> + ? ? ? ? snprintf (buf, buf_max, "%s:%d %s %s", nlp->symtab->filename,
>> + ? ? ? ? ? ? ? ? ? ?nlp->line,
>> + ? ? ? ? ? ? ? ? ? ?(nlp->function) ? SYMBOL_LINKAGE_NAME (nlp->function)
>> : "",
>> + ? ? ? ? ? ? ? ? ? ?paddress (gdbarch, nlp->addr));
>> + ? ? ? ?}
>> + ? ? ?else
>> + ? ? ? ?{
>> + ? ? ? ? ?if (nlp->symtab)
>> + ? ? ? ? ? snprintf (buf, buf_max, "%s %d %s",
>> + ? ? ? ? ? ? ? ? ? ? ?(nlp->function) ? SYMBOL_LINKAGE_NAME
>> (nlp->function) : "",
>> + ? ? ? ? ? ? ? ? ? ? ?nlp->line, paddress (gdbarch, nlp->addr));
>> + ? ? ? ? ?else
>> + ? ? ? ? ? ?snprintf (buf, buf_max, "%s %s",
>> + ? ? ? ? ? ? ? ? ? ? ?(nlp->function) ? SYMBOL_LINKAGE_NAME
>> (nlp->function) : "",
>> + ? ? ? ? ? ? ? ? ? ? ?paddress (gdbarch, nlp->addr));
>> + ? ? ? ?}
>> + ? ?}
>> +}
>> +
>> +static void
>> +record_pic_edge (char *buf, int buf_max, struct edge_list *elp,
>> + ? ? ? ? ? ? ? ?char *node, char *prev_node)
>> +{
>> + ?if (elp->frame_diff)
>> + ? ?{
>> + ? ? ?if (elp->is_return)
>> + ? ? ? ?snprintf (buf, buf_max, "edge: {color:blue sourcename: \"%s\" "
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"targetname: \"%s\"",
>> + ? ? ? ? ? ? ? ? prev_node, node);
>> + ? ? ?else
>> + ? ? ? ?snprintf (buf, buf_max, "edge: {color:red sourcename: \"%s\" "
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"targetname: \"%s\"",
>> + ? ? ? ? ? ? ? ? prev_node, node);
>> + ? ?}
>> + ?else
>> + ? ?snprintf (buf, buf_max,
>> + ? ? ? ? ? ? ?"nearedge: {sourcename: \"%s\" targetname: \"%s\"",
>> + ? ? ? ? ? ? ?prev_node, node);
>> +}
>> +
>> +/* Save the execution log to a vcg file. ?*/
>> +
>> +static void
>> +cmd_record_pic (char *args, int from_tty)
>> +{
>> + ?char *recfilename, recfilename_buffer[40];
>> + ?FILE *fp;
>> + ?struct cleanup *old_cleanups, *set_cleanups;
>> + ?struct regcache *regcache;
>> + ?struct gdbarch *gdbarch;
>> + ?struct record_entry *cur_record_list;
>> + ?char prev_node[256], line[256];
>> + ?CORE_ADDR prev_addr;
>> + ?struct frame_id fi, caller_fi, prev_fi, prev_caller_fi;
>> + ?struct edge_list *edge_list_tail = NULL;
>> + ?struct node_list *node_list_tail = NULL;
>> + ?struct symtab_and_line sal, prev_sal;
>> + ?struct node_list *prev_nlp;
>> + ?struct node_list prev_nlp_real;
>> +
>> + ?/* Check if record target is running. ?*/
>> + ?if (current_target.to_stratum != record_stratum)
>> + ? ?error (_("This command can only be used with target 'record' \
>> +or target 'record-core'."));
>> +
>> + ?if (args && *args)
>> + ? ?recfilename = args;
>> + ?else
>> + ? ?{
>> + ? ? ?/* Default recfile name is "gdb_record_PID.vcg". ?*/
>> + ? ? ?snprintf (recfilename_buffer, sizeof (recfilename_buffer),
>> + ? ? ? ? ? ? ? ?"gdb_record_%d.vcg", PIDGET (inferior_ptid));
>> + ? ? ?recfilename = recfilename_buffer;
>> + ? ?}
>> +
>> + ?/* Open the output file. ?*/
>> + ?fp = fopen (recfilename, "wb");
>> + ?if (!fp)
>> + ? ?error (_("Unable to open file '%s'"), recfilename);
>> +
>> + ?old_cleanups = make_cleanup (record_pic_cleanups, fp);
>> +
>> + ?/* Save the current record entry to "cur_record_list". ?*/
>> + ?cur_record_list = record_list;
>> +
>> + ?/* Get the values of regcache and gdbarch. ?*/
>> + ?regcache = get_current_regcache ();
>> + ?gdbarch = get_regcache_arch (regcache);
>> +
>> + ?/* Disable the GDB operation record. ?*/
>> + ?set_cleanups = record_gdb_operation_disable_set ();
>> +
>> + ?/* Reverse execute to the begin of record list. ?*/
>> + ?while (1)
>> + ? ?{
>> + ? ? ?/* Check for beginning and end of log. ?*/
>> + ? ? ?if (record_list == &record_first)
>> + ? ? ? ?break;
>> +
>> + ? ? ?record_exec_insn (regcache, gdbarch, record_list);
>> +
>> + ? ? ?if (record_list->prev)
>> + ? ? ? ?record_list = record_list->prev;
>> + ? ?}
>> +
>> + ?/* Write out the record log. ?*/
>> + ?/* Write the head. ?*/
>> + ?record_pic_fputs (fp, "graph: {title: \"GDB process record\"\n");
>> +
>> + ?/* Write the first node. ?*/
>> + ?record_pic_fputs (fp, "node: {title: \"[BEGIN]\"}\n");
>> +
>> + ?/* Initialization. ?*/
>> + ?snprintf (prev_node, 256, "[BEGIN]");
>> + ?prev_fi = null_frame_id;
>> + ?prev_caller_fi = null_frame_id;
>> + ?prev_addr = 0;
>> + ?prev_sal.symtab = NULL;
>> + ?prev_nlp_real.addr = 0;
>> + ?prev_nlp = &prev_nlp_real;
>> +
>> + ?/* Save the entries to fp and forward execute to the end of
>> + ? ? record list. ?*/
>> + ?record_list = &record_first;
>> + ?while (1)
>> + ? ?{
>> + ? ? ?if (record_list->type == record_end)
>> + ? ? ? ?{
>> + ? ? ? ? ?int frame_diff = 0;
>> + ? ? ? ? ?CORE_ADDR addr = regcache_read_pc (regcache);
>> +
>> + ? ? ? ? ?/* Check if the ADDR is stil in the same line with the
>> + ? ? ? ? ? ? prev cycle. ?*/
>> + ? ? ? ? ?if (prev_sal.symtab
>> + ? ? ? ? ? ? ?&& addr >= prev_sal.pc && addr < prev_sal.end)
>> + ? ? ? ? ? ?goto exec;
>> + ? ? ? ? ?sal = find_pc_line (addr, 0);
>> +
>> + ? ? ? ? ?if (record_pic_hide_nosource && !sal.symtab)
>> + ? ? ? ? ? ?goto exec;
>> +
>> + ? ? ? ? ?/* Check if the inferior is in same frame with prev cycle.
>> + ? ? ? ? ? ? Check both the current fi and caller fi because the last
>> + ? ? ? ? ? ? addr of function is different with current function. ?*/
>> + ? ? ? ? ?reinit_frame_cache ();
>> + ? ? ? ? ?fi = get_frame_id (get_current_frame ());
>> + ? ? ? ? ?caller_fi = frame_unwind_caller_id (get_current_frame ());
>> + ? ? ? ? ?if (!frame_id_eq (prev_fi, fi)
>> + ? ? ? ? ? ? ?&& !frame_id_eq (prev_caller_fi, caller_fi))
>> + ? ? ? ? ? ?frame_diff = 1;
>> +
>> + ? ? ? ? ?if (set_record_pic_type == record_pic_line || frame_diff)
>> + ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ?int is_return = 0;
>> + ? ? ? ? ? ? ?struct node_list *nlp = NULL;
>> + ? ? ? ? ? ? ?struct edge_list *elp = NULL;
>> + ? ? ? ? ? ? ?char node[256];
>> + ? ? ? ? ? ? ?struct minimal_symbol *function;
>> +
>> + ? ? ? ? ? ? /* Get the node addr. ?*/
>> + ? ? ? ? ? ? ?if (set_record_pic_type == record_pic_function)
>> + ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ?/* Get the start addr of function. ?*/
>> + ? ? ? ? ? ? ? ? ?addr = get_pc_function_start (addr);
>> + ? ? ? ? ? ? ? ? ?if (addr == 0)
>> + ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ?if (record_pic_hide_nofunction)
>> + ? ? ? ? ? ? ? ? ? ? ? ?goto exec;
>> + ? ? ? ? ? ? ? ? ? ? ?addr = regcache_read_pc (regcache);
>> + ? ? ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ?else
>> + ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ?/* Get the start addr of line. ?*/
>> + ? ? ? ? ? ? ? ? ?if (sal.symtab)
>> + ? ? ? ? ? ? ? ? ? ?addr = sal.pc;
>> + ? ? ? ? ? ? ? ?}
>> +
>> + ? ? ? ? ? ? ?function = lookup_minimal_symbol_by_pc (addr);
>> + ? ? ? ? ? ? ?if (!function && record_pic_hide_nofunction)
>> + ? ? ? ? ? ? ? ?goto exec;
>> +
>> + ? ? ? ? ? ? ?if (frame_id_eq (fi, prev_caller_fi))
>> + ? ? ? ? ? ? ? ?is_return = 1;
>> +
>> + ? ? ? ? ? ? ?if (record_pic_hide_same)
>> + ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ?/* Check if addr in node_list. ?*/
>> + ? ? ? ? ? ? ? ? ?for (nlp = node_list; nlp; nlp = nlp->next)
>> + ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ?if (nlp->addr == addr)
>> + ? ? ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ? ? if (!is_return
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? || set_record_pic_type !=
>> record_pic_function)
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?nlp->count ++;
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?break;
>> + ? ? ? ? ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ? ? ?}
>> +
>> + ? ? ? ? ? ? ? ? ?/* Check if prev_addr and addr in edge_list. ?*/
>> + ? ? ? ? ? ? ? ? if (nlp)
>> + ? ? ? ? ? ? ? ? ? {
>> + ? ? ? ? ? ? ? ? ? ? ?for (elp = edge_list; elp; elp = elp->next)
>> + ? ? ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?if (elp->s->addr == prev_addr &&
>> elp->t->addr == addr)
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?elp->count ++;
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ? ? }
>> + ? ? ? ? ? ? ? ?}
>> +
>> + ? ? ? ? ? ? ?if (!nlp)
>> + ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ?struct node_list nl;
>> +
>> + ? ? ? ? ? ? ? ? ?nl.addr = addr;
>> + ? ? ? ? ? ? ? ? ?if (frame_diff && sal.symtab)
>> + ? ? ? ? ? ? ? ? ? ?nl.showall = 1;
>> + ? ? ? ? ? ? ? ? ?else
>> + ? ? ? ? ? ? ? ? ? ?nl.showall = 0;
>> + ? ? ? ? ? ? ? ? ?nl.symtab = sal.symtab;
>> + ? ? ? ? ? ? ? ? ?nl.line = sal.line;
>> + ? ? ? ? ? ? ? ? ?nl.function = function;
>> +
>> + ? ? ? ? ? ? ? ? ?if (record_pic_hide_same)
>> + ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ?nlp = xmalloc (sizeof (struct node_list));
>> + ? ? ? ? ? ? ? ? ? ? ?*nlp = nl;
>> + ? ? ? ? ? ? ? ? ? ? ?nlp->count = 1;
>> +
>> + ? ? ? ? ? ? ? ? ? ? ?/* Add node to node_list. ?*/
>> + ? ? ? ? ? ? ? ? ? ? ?nlp->next = NULL;
>> + ? ? ? ? ? ? ? ? ? ? if (node_list_tail)
>> + ? ? ? ? ? ? ? ? ? ? ? ?node_list_tail->next = nlp;
>> + ? ? ? ? ? ? ? ? ? ? if (node_list == NULL)
>> + ? ? ? ? ? ? ? ? ? ? ? node_list = nlp;
>> + ? ? ? ? ? ? ? ? ? ? ?node_list_tail = nlp;
>> + ? ? ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ? ?else
>> + ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ?/* Draw the node. ?*/
>> + ? ? ? ? ? ? ? ? ? ? ?record_pic_node (node, 256, gdbarch,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? set_record_pic_type, &nl);
>> + ? ? ? ? ? ? ? ? ? ? snprintf (line, 256, "%s i:%s", node,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pulongest (record_list->u.end.insn_num));
>> + ? ? ? ? ? ? ? ? ? ? strcpy (node, line);
>> + ? ? ? ? ? ? ? ? ? ? ?snprintf (line, 256, "node: {title: \"%s\"}\n",
>> node);
>> + ? ? ? ? ? ? ? ? ? ? ?record_pic_fputs (fp, line);
>> + ? ? ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ?}
>> +
>> + ? ? ? ? ? ? ?if (!elp)
>> + ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ?struct edge_list el;
>> +
>> + ? ? ? ? ? ? ? ? ?el.is_return = is_return;
>> + ? ? ? ? ? ? ? ? ?el.frame_diff = frame_diff;
>> +
>> + ? ? ? ? ? ? ? ? ?if (record_pic_hide_same)
>> + ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ?elp = xmalloc (sizeof (struct edge_list));
>> + ? ? ? ? ? ? ? ? ? ? ?*elp = el;
>> + ? ? ? ? ? ? ? ? ? ? elp->s = prev_nlp;
>> + ? ? ? ? ? ? ? ? ? ? ?elp->t = nlp;
>> + ? ? ? ? ? ? ? ? ? ? ?elp->count = 1;
>> +
>> + ? ? ? ? ? ? ? ? ? ? ?/* Add edge to edge_list. ?*/
>> + ? ? ? ? ? ? ? ? ? ? ?elp->next = NULL;
>> + ? ? ? ? ? ? ? ? ? ? if (edge_list_tail)
>> + ? ? ? ? ? ? ? ? ? ? ? ?edge_list_tail->next = elp;
>> + ? ? ? ? ? ? ? ? ? ? if (edge_list == NULL)
>> + ? ? ? ? ? ? ? ? ? ? ? edge_list = elp;
>> + ? ? ? ? ? ? ? ? ? ? ?edge_list_tail = elp;
>> + ? ? ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ? ?else
>> + ? ? ? ? ? ? ? ? ? ?{
>> + ? ? ? ? ? ? ? ? ? ? ?/* Draw the edge. ?*/
>> + ? ? ? ? ? ? ? ? ? ? ?record_pic_edge (line, 256, &el, node, prev_node);
>> + ? ? ? ? ? ? ? ? ? ? ?record_pic_fputs (fp, line);
>> + ? ? ? ? ? ? ? ? ? ? record_pic_fputs (fp, " }\n");
>> + ? ? ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ?}
>> +
>> + ? ? ? ? ? ? ?if (record_pic_hide_same)
>> + ? ? ? ? ? ? ? ?prev_nlp = nlp;
>> + ? ? ? ? ? ? ?else
>> + ? ? ? ? ? ? ? ?snprintf (prev_node, 256, "%s", node);
>> + ? ? ? ? ? ? ?prev_addr = addr;
>> + ? ? ? ? ? ?}
>> +
>> + ? ? ? ? ?prev_sal = sal;
>> + ? ? ? ? ?prev_fi = fi;
>> + ? ? ? ? ?prev_caller_fi = caller_fi;
>> + ? ? ? ?}
>> +
>> +exec:
>> + ? ? ?/* Execute entry. ?*/
>> + ? ? ?record_exec_insn (regcache, gdbarch, record_list);
>> +
>> + ? ? ?if (record_list->next)
>> + ? ? ? ?record_list = record_list->next;
>> + ? ? ?else
>> + ? ? ? ?break;
>> + ? ?}
>> +
>> + ?if (record_pic_hide_same)
>> + ? ?{
>> + ? ? ?struct node_list *nlp = NULL;
>> + ? ? ?struct edge_list *elp = NULL;
>> + ? ? ?char node[256];
>> +
>> + ? ? ?for (nlp = node_list; nlp; nlp = nlp->next)
>> + ? ? ? ?{
>> + ? ? ? ? ?/* Draw the node. ?*/
>> + ? ? ? ? ?record_pic_node (node, 256, gdbarch, set_record_pic_type, nlp);
>> + ? ? ? ? ?snprintf (line, 256, "node: {title: \"%s c:%d\"}\n", node,
>> + ? ? ? ? ? ? ? ? ? nlp->count);
>> + ? ? ? ? ?record_pic_fputs (fp, line);
>> + ? ? ? }
>> +
>> + ? ? ?record_pic_node (node, 256, gdbarch, set_record_pic_type,
>> edge_list->t);
>> + ? ? ?snprintf (line, 256,
>> + ? ? ? ? ? ? ? "nearedge: {color:red sourcename: \"[BEGIN]\" targetname:
>> \"%s c:%d\"}\n",
>> + ? ? ? ? ? ? ? node, edge_list->count);
>> + ? ? ?record_pic_fputs (fp, line);
>> + ? ? ?for (elp = edge_list->next; elp; elp = elp->next)
>> + ? ? ? ?{
>> + ? ? ? ? ?/* Draw the edge. ?*/
>> + ? ? ? ? record_pic_node (prev_node, 256, gdbarch, set_record_pic_type,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?elp->s);
>> + ? ? ? ? snprintf (line, 256, "%s c:%d", prev_node, elp->s->count);
>> + ? ? ? ? strcpy (prev_node, line);
>> + ? ? ? ? record_pic_node (node, 256, gdbarch, set_record_pic_type,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?elp->t);
>> + ? ? ? ? snprintf (line, 256, "%s c:%d", node, elp->t->count);
>> + ? ? ? ? strcpy (node, line);
>> + ? ? ? ? ?record_pic_edge (line, 256, elp, node, prev_node);
>> + ? ? ? ? ?record_pic_fputs (fp, line);
>> + ? ? ? ? ?snprintf (line, 256, " label: \"c:%d\"}\n", elp->count);
>> + ? ? ? ? record_pic_fputs (fp, line);
>> + ? ? ? ?}
>> + ? ?}
>> +
>> + ?/* Write the last node. ?*/
>> + ?record_pic_fputs (fp, "node: {title: \"[END]\"}\n");
>> + ?snprintf (line, 256,
>> + ? ? ? ? ? "nearedge: {color:red sourcename: \"%s\" targetname: \"[END]\"
>> }\n",
>> + ? ? ? ? ? prev_node);
>> + ?record_pic_fputs (fp, line);
>> +
>> + ?/* Write the tail. ?*/
>> + ?record_pic_fputs (fp, "}\n");
>> +
>> + ?/* Reverse execute to cur_record_list. ?*/
>> + ?while (1)
>> + ? ?{
>> + ? ? ?/* Check for beginning and end of log. ?*/
>> + ? ? ?if (record_list == cur_record_list)
>> + ? ? ? ?break;
>> +
>> + ? ? ?record_exec_insn (regcache, gdbarch, record_list);
>> +
>> + ? ? ?if (record_list->prev)
>> + ? ? ? ?record_list = record_list->prev;
>> + ? ?}
>> +
>> + ?do_cleanups (set_cleanups);
>> + ?do_cleanups (old_cleanups);
>> +
>> + ?/* Succeeded. ?*/
>> + ?printf_filtered (_("Saved file %s with execution log.\n"),
>> + ? ? ? ? ? ? ? ? ?recfilename);
>> +}
>> +
>> ?/* record_goto_insn -- rewind the record log (forward or backward,
>> ? ?depending on DIR) to the given entry, changing the program state
>> ? ?correspondingly. ?*/
>> @@ -2730,4 +3211,60 @@ record/replay buffer. ?Zero means unlimi
>> ?Restore the program to its state at instruction number N.\n\
>> ?Argument is instruction number, as shown by 'info record'."),
>> ? ? ? ? ? &record_cmdlist);
>> +
>> + ?/* For "record pic" command. ?*/
>> + ?c = add_cmd ("pic", class_obscure, cmd_record_pic,
>> + ? ? ? ? ? ? ?_("Save the execution log to a vcg file.\n\
>> +Argument is optional filename.\n\
>> +Default filename is 'gdb_record_<process_id>.vcg'."),
>> + ? ? ? ? ? ? ?&record_cmdlist);
>> + ?set_cmd_completer (c, filename_completer);
>> + ?add_prefix_cmd ("pic", class_support, set_record_pic_command,
>> + ? ? ? ? ? ? ? ? _("Set record pic options"), &set_record_pic_cmdlist,
>> + ? ? ? ? ? ? ? ? "set record pic ", 0, &set_record_cmdlist);
>> + ?add_prefix_cmd ("pic", class_support, show_record_pic_command,
>> + ? ? ? ? ? ? ? ? _("Show record pic options"), &show_record_pic_cmdlist,
>> + ? ? ? ? ? ? ? ? "show record pic ", 0, &show_record_cmdlist);
>> + ?add_setshow_enum_cmd ("type", no_class,
>> + ? ? ? ? ? ? ? ? ? ? ? record_pic_enum, &set_record_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."),
>> + ? ? ? ? ? ? ? ? ? ? ? NULL, NULL,
>> + ? ? ? ? ? ? ? ? ? ? ? &set_record_pic_cmdlist,
>> &show_record_pic_cmdlist);
>> + ?add_setshow_boolean_cmd ("hide-nofunction", no_class,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?&record_pic_hide_nofunction, _("\
>> +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."),
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?NULL, NULL,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?&set_record_pic_cmdlist,
>> &show_record_pic_cmdlist);
>> + ?add_setshow_boolean_cmd ("hide-nosource", no_class,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?&record_pic_hide_nosource, _("\
>> +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."),
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?NULL, NULL,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?&set_record_pic_cmdlist,
>> &show_record_pic_cmdlist);
>> + ?add_setshow_boolean_cmd ("hide-same", no_class,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?&record_pic_hide_same, _("\
>> +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."),
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?NULL, NULL,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ?&set_record_pic_cmdlist,
>> &show_record_pic_cmdlist);
>> ?}
>>
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]