extern void (*readline_begin_hook) PARAMS ((char *, ...));
extern char * (*readline_hook) PARAMS ((char *));
extern void (*readline_end_hook) PARAMS ((void));
+extern void x_command PARAMS ((char *, int));
/* If this definition isn't overridden by the header files, assume
that isatty and fileno exist on this system. */
t->language = current_language->la_language;
t->input_radix = input_radix;
t->line_number = sal.line;
- t->enabled = enabled;
- t->next = 0;
- t->step_count = 0;
- t->pass_count = 0;
+ t->enabled = enabled;
+ t->next = 0;
+ t->step_count = 0;
+ t->pass_count = 0;
+ t->addr_string = NULL;
/* Add this tracepoint to the end of the chain
so that a list of tracepoints will come out in order
struct symtabs_and_lines sals;
struct symtab_and_line sal;
struct tracepoint *t;
- char *addr_start = 0, *addr_end = 0, *cond_start = 0, *cond_end = 0;
+ char *addr_start = 0, *addr_end = 0;
int i;
if (!arg || !*arg)
t->addr_string = canonical[i];
else if (addr_start)
t->addr_string = savestring (addr_start, addr_end - addr_start);
- if (cond_start)
- t->cond_string = savestring (cond_start, cond_end - cond_start);
/* Let the UI know of any additions */
if (create_tracepoint_hook)
enum tracepoint_opcode opcode;
{
struct tracepoint *t2;
- struct action_line *action, *next;
switch (opcode) {
case enable:
t->enabled = enabled;
+ if (modify_tracepoint_hook)
+ modify_tracepoint_hook (t);
break;
case disable:
t->enabled = disabled;
+ if (modify_tracepoint_hook)
+ modify_tracepoint_hook (t);
break;
case delete:
if (tracepoint_chain == t)
if (delete_tracepoint_hook)
delete_tracepoint_hook (t);
- if (t->cond_string)
- free (t->cond_string);
if (t->addr_string)
free (t->addr_string);
if (t->source_file)
free (t->source_file);
- for (action = t->actions; action; action = next)
- {
- next = action->next;
- if (action->action)
- free (action->action);
- free (action);
- }
+ if (t->actions)
+ free_actions (t);
+
free (t);
break;
}
int from_tty;
enum tracepoint_opcode opcode;
{
- struct tracepoint *t;
+ struct tracepoint *t, *tmp;
int tpnum;
char *cp;
if (args == 0 || *args == 0) /* do them all */
- ALL_TRACEPOINTS (t)
+ ALL_TRACEPOINTS_SAFE (t, tmp)
tracepoint_operation (t, from_tty, opcode);
else
while (*args)
if (t1 == (struct tracepoint *) -1 || t1 == t2)
{
t2->pass_count = count;
+ if (modify_tracepoint_hook)
+ modify_tracepoint_hook (t2);
if (from_tty)
printf_filtered ("Setting tracepoint %d's passcount to %d\n",
t2->number, count);
/* Prototypes for action-parsing utility commands */
static void read_actions PARAMS((struct tracepoint *));
-static void free_actions PARAMS((struct tracepoint *));
static char *parse_and_eval_memrange PARAMS ((char *,
CORE_ADDR,
long *,
static void
end_actions_pseudocommand (args, from_tty)
+ char *args;
+ int from_tty;
{
error ("This command cannot be used at the top level.");
}
static void
while_stepping_pseudocommand (args, from_tty)
+ char *args;
+ int from_tty;
{
error ("This command can only be used in a tracepoint actions list.");
}
static void
collect_pseudocommand (args, from_tty)
+ char *args;
+ int from_tty;
{
error ("This command can only be used in a tracepoint actions list.");
}
sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
t->number);
- if (readline_begin_hook)
- (*readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
- else if (from_tty && input_from_terminal_p ())
- printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
+ if (from_tty)
+ {
+ if (readline_begin_hook)
+ (*readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
+ else if (input_from_terminal_p ())
+ printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
+ }
free_actions (t);
read_actions (t);
STEPPING = 2,
};
-static enum actionline_type validate_actionline PARAMS((char *,
+static enum actionline_type validate_actionline PARAMS((char **,
struct tracepoint *));
/* worker function */
if (readline_hook && instream == NULL)
line = (*readline_hook) (prompt);
else if (instream == stdin && ISATTY (instream))
- line = readline (prompt);
+ {
+ line = readline (prompt);
+ if (line && *line) /* add it to command history */
+ add_history (line);
+ }
else
line = gdb_readline (0);
- linetype = validate_actionline (line, t);
+ linetype = validate_actionline (&line, t);
if (linetype == BADLINE)
continue; /* already warned -- collect another line */
- temp = xmalloc (sizeof (struct action_line));
+ temp = (struct action_line *) xmalloc (sizeof (struct action_line));
temp->next = NULL;
temp->action = line;
/* worker function */
static enum actionline_type
validate_actionline (line, t)
- char *line;
+ char **line;
struct tracepoint *t;
{
struct cmd_list_element *c;
value_ptr temp, temp2;
char *p;
- for (p = line; isspace (*p); )
+ for (p = *line; isspace (*p); )
p++;
/* symbol lookup etc. */
if (*p == '\0') /* empty line: just prompt for another line. */
return BADLINE;
+ if (*p == '#') /* comment line */
+ return GENERIC;
+
c = lookup_cmd (&p, cmdlist, "", -1, 1);
if (c == 0)
{
p = strchr (p, ',');
else if (p[1] == '(') /* literal memrange */
- p = parse_and_eval_memrange (p, t->address,
- &typecode, &offset, &size);
+ {
+ char *temp, *newline;
+
+ newline = malloc (strlen (*line) + 32);
+ strcpy (newline, *line);
+ newline[p - *line] = '\0';
+ /* newline is now a copy of line, up to "p" (the memrange) */
+ temp = parse_and_eval_memrange (p, t->address,
+ &typecode, &offset, &size) + 1;
+ /* now compose the memrange as a literal value */
+ if (typecode == -1)
+ sprintf (newline + strlen (newline),
+ "$(0x%x, %d)",
+ offset, size);
+ else
+ sprintf (newline + strlen (newline),
+ "$($%s, 0x%x, %d)",
+ reg_names[typecode], offset, size);
+ /* now add the remainder of the old line to the new one */
+ p = newline + strlen (newline);
+ if (temp && *temp)
+ strcat (newline, temp);
+ free (*line);
+ *line = newline;
+ }
}
else
{
exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
if (exp->elts[0].opcode != OP_VAR_VALUE &&
+ exp->elts[0].opcode != UNOP_MEMVAL &&
/*exp->elts[0].opcode != OP_LONG && */
/*exp->elts[0].opcode != UNOP_CAST && */
exp->elts[0].opcode != OP_REGISTER)
return END;
else
{
- warning ("'%s' is not a supported tracepoint action.", line);
+ warning ("'%s' is not a supported tracepoint action.", *line);
return BADLINE;
}
}
/* worker function */
-static void
+void
free_actions (t)
struct tracepoint *t;
{
for (line = t->actions; line; line = next)
{
next = line->next;
+ if (line->action)
+ free (line->action);
free (line);
}
t->actions = NULL;
long *typecode, *size;
bfd_signed_vma *offset;
{
- char *start = arg;
+ char *start = arg;
struct expression *exp;
+ value_ptr val;
if (*arg++ != '$' || *arg++ != '(')
- error ("Internal: bad argument to validate_memrange: %s", start);
+ error ("Internal: bad argument to parse_and_eval_memrange: %s", start);
if (*arg == '$') /* register for relative memrange? */
{
*typecode = exp->elts[1].longconst;
}
else
- *typecode = 0;
+ *typecode = -1; /* absolute memrange; */
-#if 0
- /* While attractive, this fails for a number of reasons:
- 1) parse_and_eval_address does not deal with trailing commas,
- close-parens etc.
- 2) There is no safeguard against the user trying to use
- an out-of-scope variable in an address expression (for instance).
- 2.5) If you are going to allow semi-arbitrary expressions, you
- would need to explain which expressions are allowed, and
- which are not (which would provoke endless questions).
- 3) If you are going to allow semi-arbitrary expressions in the
- offset and size fields, then the leading "$" of a register
- name no longer disambiguates the typecode field.
- */
-
- *offset = parse_and_eval_address (arg);
- if ((arg = strchr (arg, ',')) == NULL)
- error ("missing comma for memrange: %s", start);
- else
- arg++;
-
- *size = parse_and_eval_address (arg);
- if ((arg = strchr (arg, ')')) == NULL)
- error ("missing close-parenthesis for memrange: %s", start);
- else
- arg++;
-#else
-#if 0
- /* This, on the other hand, doesn't work because "-1" is an
- expression, not an OP_LONG! Fall back to using strtol for now. */
-
- exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
- if (exp->elts[0].opcode != OP_LONG)
- error ("Bad offset operand for memrange: %s", start);
- *offset = exp->elts[2].longconst;
+ exp = parse_exp_1 (&arg, 0, 1);
+ *offset = value_as_pointer (evaluate_expression (exp));
+ /* now parse the size */
if (*arg++ != ',')
error ("missing comma for memrange: %s", start);
- exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
- if (exp->elts[0].opcode != OP_LONG)
- error ("Bad size operand for memrange: %s", start);
- *size = exp->elts[2].longconst;
+ exp = parse_exp_1 (&arg, 0, 0);
+ *size = value_as_long (evaluate_expression (exp));
- if (*size <= 0)
- error ("invalid size in memrange: %s", start);
-
- if (*arg++ != ')')
- error ("missing close-parenthesis for memrange: %s", start);
-#else
- *offset = strtol (arg, &arg, 0);
- if (*arg++ != ',')
- error ("missing comma for memrange: %s", start);
- *size = strtol (arg, &arg, 0);
- if (*size <= 0)
- error ("invalid size in memrange: %s", start);
- if (*arg++ != ')')
- error ("missing close-parenthesis for memrange: %s", start);
-#endif
-#endif
if (info_verbose)
printf_filtered ("Collecting memrange: (0x%x,0x%x,0x%x)\n",
*typecode, *offset, *size);
/* compare memranges for qsort */
static int
-memrange_cmp (a, b)
- struct memrange *a, *b;
+memrange_cmp (voidpa, voidpb)
+ void *voidpa, *voidpb;
{
+ struct memrange *a, *b;
+
+ a = (struct memrange *) voidpa;
+ b = (struct memrange *) voidpb;
+
if (a->type < b->type) return -1;
if (a->type > b->type) return 1;
if (a->type == 0)
memranges->list[b].start - memranges->list[a].end <=
MAX_REGISTER_VIRTUAL_SIZE)
{
- memranges->list[a].end = memranges->list[b].end;
+ /* memrange b starts before memrange a ends; merge them. */
+ if (memranges->list[b].end > memranges->list[a].end)
+ memranges->list[a].end = memranges->list[b].end;
continue; /* next b, same a */
}
a++; /* next a */
if (memranges->next_memrange >= memranges->listsize)
{
memranges->listsize *= 2;
- memranges->list = xrealloc (memranges->list,
+ memranges->list = (struct memrange *) xrealloc (memranges->list,
memranges->listsize);
}
- if (type != 0) /* better collect the base register! */
+ if (type != -1) /* better collect the base register! */
add_register (memranges, type);
}
case LOC_STATIC:
offset = SYMBOL_VALUE_ADDRESS (sym);
if (info_verbose)
- printf_filtered ("LOC_STATIC %s: collect %d bytes "
- "at 0x%08x\n",
+ printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
SYMBOL_NAME (sym), len, offset);
- add_memrange (collect, 0, offset, len); /* 0 == memory */
+ add_memrange (collect, -1, offset, len); /* 0 == memory */
break;
case LOC_REGISTER:
case LOC_REGPARM:
struct action_line *action;
bfd_signed_vma offset;
long i;
+ value_ptr tempval;
struct collection_list *collect;
struct cmd_list_element *cmd;
while (isspace (*action_exp))
action_exp++;
+ if (*action_exp == '#') /* comment line */
+ return;
+
cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
if (cmd == 0)
error ("Bad action list item: %s", action_exp);
printf_filtered ("OP_REGISTER: ");
add_register (collect, i);
break;
+
+ case UNOP_MEMVAL:
+ /* safe because we know it's a simple expression */
+ tempval = evaluate_expression (exp);
+ addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
+ len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
+ add_memrange (collect, -1, addr, len);
+ break;
+
case OP_VAR_VALUE:
collect_symbol (collect, exp->elts[2].symbol);
break;
else
len = 4;
- add_memrange (collect, 0, addr, len);
+ add_memrange (collect, -1, addr, len);
break;
#endif
}
memrange_sortmerge (&tracepoint_list);
memrange_sortmerge (&stepping_list);
- *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
- *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
+ *tdp_actions = stringify_collection_list (&tracepoint_list, tdp_buff);
+ *stepping_actions = stringify_collection_list (&stepping_list, step_buff);
}
static char target_buf[2048];
if (tdp_actions)
{
if (strlen (buf) + strlen (tdp_actions) >= sizeof (buf))
- error ("Actions for tracepoint %d too complex; "
- "please simplify.", t->number);
+ error ("Actions for tracepoint %d too complex; please simplify.",
+ t->number);
strcat (buf, tdp_actions);
}
if (stepping_actions)
{
strcat (buf, "S");
if (strlen (buf) + strlen (stepping_actions) >= sizeof (buf))
- error ("Actions for tracepoint %d too complex; "
- "please simplify.", t->number);
+ error ("Actions for tracepoint %d too complex; please simplify.",
+ t->number);
strcat (buf, stepping_actions);
}
}
set_traceframe_num (-1); /* all old traceframes invalidated */
set_tracepoint_num (-1);
set_traceframe_context(-1);
+ trace_running_p = 1;
}
else
printf_filtered ("Trace can only be run on remote targets.\n");
remote_get_noisy_reply (target_buf);
if (strcmp (target_buf, "OK"))
error ("Bogus reply from target: %s", target_buf);
+ trace_running_p = 0;
}
else
error ("Trace can only be run on remote targets.");
}
+unsigned long trace_running_p;
+
/* tstatus command */
static void
trace_status_command (args, from_tty)
{
putpkt ("qTStatus");
remote_get_noisy_reply (target_buf);
- if (strcmp (target_buf, "OK"))
- error ("Bogus reply from target: %s", target_buf);
+
+ if (target_buf[0] != 'T' ||
+ (target_buf[1] != '0' && target_buf[1] != '1'))
+ error ("Bogus reply from target: %s", target_buf);
+
+ /* exported for use by the GUI */
+ trace_running_p = (target_buf[1] == '1');
}
else
error ("Trace can only be run on remote targets.");
/* Worker function for the various flavors of the tfind command */
static void
-finish_tfind_command (reply, from_tty)
- char *reply;
+finish_tfind_command (msg, from_tty)
+ char *msg;
int from_tty;
{
int target_frameno = -1, target_tracept = -1;
+ CORE_ADDR old_frame_addr;
+ struct symbol *old_func;
+ char *reply;
+
+ old_frame_addr = FRAME_FP (get_current_frame ());
+ old_func = find_pc_function (read_pc ());
+
+ putpkt (msg);
+ reply = remote_get_noisy_reply (msg);
while (reply && *reply)
switch (*reply) {
printf_filtered ("End of trace buffer.\n");
/* The following will not recurse, since it's special-cased */
trace_find_command ("-1", from_tty);
+ reply = NULL; /* break out of loop,
+ (avoid recursive nonsense) */
}
}
break;
select_frame (get_current_frame (), 0);
set_traceframe_num (target_frameno);
set_tracepoint_num (target_tracept);
- set_traceframe_context ((get_current_frame ())->pc);
+ if (target_frameno == -1)
+ set_traceframe_context (-1);
+ else
+ set_traceframe_context (read_pc ());
if (from_tty)
- print_stack_frame (selected_frame, selected_frame_level, 1);
+ {
+ int source_only;
+
+ /* NOTE: in immitation of the step command, try to determine
+ whether we have made a transition from one function to another.
+ If so, we'll print the "stack frame" (ie. the new function and
+ it's arguments) -- otherwise we'll just show the new source line.
+
+ This determination is made by checking (1) whether the current
+ function has changed, and (2) whether the current FP has changed.
+ Hack: if the FP wasn't collected, either at the current or the
+ previous frame, assume that the FP has NOT changed. */
+
+ if (old_func == find_pc_function (read_pc ()) &&
+ (old_frame_addr == 0 ||
+ FRAME_FP (get_current_frame ()) == 0 ||
+ old_frame_addr == FRAME_FP (get_current_frame ())))
+ source_only = -1;
+ else
+ source_only = 1;
+
+ print_stack_frame (selected_frame, selected_frame_level, source_only);
+ do_displays ();
+ }
}
/* trace_find_command takes a trace frame number n,
{
if (traceframe_number == -1)
error ("not debugging trace buffer");
- else if (traceframe_number == 0)
+ else if (from_tty && traceframe_number == 0)
error ("already at start of trace buffer");
frameno = traceframe_number - 1;
}
-#if 0
- else if (0 == strcasecmp (args, "start"))
- frameno = 0;
- else if (0 == strcasecmp (args, "none") ||
- 0 == strcasecmp (args, "end"))
- frameno = -1;
-#endif
else
frameno = parse_and_eval_address (args);
sprintf (target_buf, "QTFrame:%x", frameno);
+#if 0
putpkt (target_buf);
tmp = remote_get_noisy_reply (target_buf);
if (frameno == -1) /* end trace debugging */
{ /* hopefully the stub has complied! */
- if (0 != strcmp (tmp, "F-1"))
+ if (0 != strcmp (tmp, "OK"))
error ("Bogus response from target: %s", tmp);
- flush_cached_frames ();
- registers_changed ();
- select_frame (get_current_frame (), 0);
- set_traceframe_num (-1);
- set_tracepoint_num (-1);
- set_traceframe_context (-1);
-
- if (from_tty)
- print_stack_frame (selected_frame, selected_frame_level, 1);
+ finish_tfind_command (NULL, from_tty);
}
else
finish_tfind_command (tmp, from_tty);
+#else
+ finish_tfind_command (target_buf, from_tty);
+#endif
}
else
error ("Trace can only be run on remote targets.");
pc = parse_and_eval_address (args);
sprintf (target_buf, "QTFrame:pc:%x", pc);
+#if 0
putpkt (target_buf);
tmp = remote_get_noisy_reply (target_buf);
finish_tfind_command (tmp, from_tty);
+#else
+ finish_tfind_command (target_buf, from_tty);
+#endif
}
else
error ("Trace can only be run on remote targets.");
tdp = parse_and_eval_address (args);
sprintf (target_buf, "QTFrame:tdp:%x", tdp);
+#if 0
putpkt (target_buf);
tmp = remote_get_noisy_reply (target_buf);
finish_tfind_command (tmp, from_tty);
+#else
+ finish_tfind_command (target_buf, from_tty);
+#endif
}
else
error ("Trace can only be run on remote targets.");
sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
else /* find OUTSIDE OF range of CURRENT line */
sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
+#if 0
putpkt (target_buf);
tmp = remote_get_noisy_reply (target_buf);
finish_tfind_command (tmp, from_tty);
+#else
+ finish_tfind_command (target_buf, from_tty);
+#endif
do_cleanups (old_chain);
}
else
}
sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
+#if 0
putpkt (target_buf);
tmp = remote_get_noisy_reply (target_buf);
finish_tfind_command (tmp, from_tty);
+#else
+ finish_tfind_command (target_buf, from_tty);
+#endif
}
else
error ("Trace can only be run on remote targets.");
}
sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
+#if 0
putpkt (target_buf);
tmp = remote_get_noisy_reply (target_buf);
finish_tfind_command (tmp, from_tty);
+#else
+ finish_tfind_command (target_buf, from_tty);
+#endif
}
else
error ("Trace can only be run on remote targets.");
actionline++;
fprintf (fp, "%s%s\n", indent, actionline);
- cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
- if (cmd == 0)
- error ("Bad action list item: %s", actionline);
- if (cmd->function.cfunc == while_stepping_pseudocommand)
- indent = i2;
- else if (cmd->function.cfunc == end_actions_pseudocommand)
- indent = i1;
+ if (*actionline != '#') /* skip for comment lines */
+ {
+ cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
+ if (cmd == 0)
+ error ("Bad action list item: %s", actionline);
+ if (cmd->function.cfunc == while_stepping_pseudocommand)
+ indent = i2;
+ else if (cmd->function.cfunc == end_actions_pseudocommand)
+ indent = i1;
+ }
}
}
}
/* The collection actions to be done while stepping are
bracketed by the commands "while-stepping" and "end". */
+ if (*action_exp == '#') /* comment line */
+ continue;
+
cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
if (cmd == 0)
error ("Bad action list item: %s", action_exp);
if (tracepoint_list.list == NULL)
{
tracepoint_list.listsize = 128;
- tracepoint_list.list = xmalloc
+ tracepoint_list.list = (struct memrange *) xmalloc
(tracepoint_list.listsize * sizeof (struct memrange));
}
if (stepping_list.list == NULL)
{
stepping_list.listsize = 128;
- stepping_list.list = xmalloc
+ stepping_list.list = (struct memrange *) xmalloc
(stepping_list.listsize * sizeof (struct memrange));
}