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 12:46, Hui Zhu <teawater@gmail.com> wrote:
> 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

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 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]