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 *,
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. */
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;
-
-#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++;
+ *typecode = -1; /* absolute memrange; */
- *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;
-
- if (*size <= 0)
- error ("invalid size in memrange: %s", start);
+ exp = parse_exp_1 (&arg, 0, 0);
+ *size = value_as_long (evaluate_expression (exp));
- 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)
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;
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.");
{
int source_only;
- if (old_frame_addr == FRAME_FP (get_current_frame ()) &&
- old_func == find_pc_function (read_pc ()))
+ /* 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;
{
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 (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));
}