/* Tracing functionality for remote targets in custom GDB protocol
- Copyright 1997 Free Software Foundation, Inc.
+ Copyright 1997, 1998 Free Software Foundation, Inc.
This file is part of GDB.
#include "ax-gdb.h"
/* readline include files */
-#include "readline.h"
-#include "history.h"
+#include <readline/readline.h>
+#include <readline/history.h>
/* readline defines this. */
#undef savestring
if (sal.symtab == NULL)
t->source_file = NULL;
else
- {
- char *p;
-
- t->source_file = (char *) xmalloc (strlen (sal.symtab->filename) +
- strlen (sal.symtab->dirname) + 2);
-
- strcpy (t->source_file, sal.symtab->dirname);
- p = t->source_file;
- while (*p)
- p++;
- if (*(--p) != '/') /* Will this work on Windows? */
- strcat (t->source_file, "/");
- strcat (t->source_file, sal.symtab->filename);
- }
+ t->source_file = savestring (sal.symtab->filename,
+ strlen (sal.symtab->filename));
- t->language = current_language->la_language;
+ t->section = sal.section;
+ t->language = current_language->la_language;
t->input_radix = input_radix;
t->line_number = sal.line;
t->enabled = enabled;
t->enabled == enabled ? "y" : "n");
if (addressprint)
printf_filtered ("%s ",
- local_hex_string_custom ((unsigned long) t->address,
+ local_hex_string_custom ((unsigned long) t->address,
"08l"));
printf_filtered ("%-5d %-5d ", t->pass_count, t->step_count);
if (t->source_file)
{
- sym = find_pc_function (t->address);
+ sym = find_pc_sect_function (t->address, t->section);
if (sym)
{
fputs_filtered ("in ", gdb_stdout);
if (job_control)
signal (STOP_SIGNAL, stop_sig);
#endif
- old_chain = make_cleanup (free_actions, (void *) t);
+ old_chain = make_cleanup ((make_cleanup_func) free_actions, (void *) t);
while (1)
{
/* Make sure that all output has been output. Some machines may let
/* else fall thru, treat p as an expression and parse it! */
}
exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
- old_chain = make_cleanup (free_current_contents, &exp);
+ old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
+ &exp);
if (exp->elts[0].opcode == OP_VAR_VALUE)
if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
/* we have something to collect, make sure that the expr to
bytecode translator can handle it and that it's not too long */
- aexpr = gen_trace_for_expr(exp);
- (void) make_cleanup (free_agent_expr, aexpr);
+ aexpr = gen_trace_for_expr (t->address, exp);
+ (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);
if (aexpr->len > MAX_AGENT_EXPR_LEN)
error ("expression too complicated, try simplifying");
/* Add a symbol to a collection list */
static void
-collect_symbol (collect, sym)
+collect_symbol (collect, sym, frame_regno, frame_offset)
struct collection_list *collect;
struct symbol *sym;
+ long frame_regno;
+ long frame_offset;
{
unsigned long len;
unsigned long reg;
if (info_verbose)
printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
add_register (collect, reg);
+ /* check for doubles stored in two registers */
+ /* FIXME: how about larger types stored in 3 or more regs? */
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
+ len > REGISTER_RAW_SIZE (reg))
+ add_register (collect, reg + 1);
break;
- case LOC_ARG:
case LOC_REF_ARG:
- printf_filtered ("Sorry, don't know how to do LOC_ARGs yet.\n");
+ printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
printf_filtered (" (will not collect %s)\n",
SYMBOL_NAME (sym));
break;
+ case LOC_ARG:
+ reg = frame_regno;
+ offset = frame_offset + SYMBOL_VALUE (sym);
+ if (info_verbose)
+ {
+ printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
+ SYMBOL_NAME (sym), len);
+ printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
+ }
+ add_memrange (collect, reg, offset, len);
+ break;
case LOC_REGPARM_ADDR:
reg = SYMBOL_VALUE (sym);
offset = 0;
if (info_verbose)
{
- printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset %d from reg %d\n",
- SYMBOL_NAME (sym), len, offset, reg);
+ printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset",
+ SYMBOL_NAME (sym), len);
+ printf_filtered (" %d from reg %d\n", offset, reg);
}
add_memrange (collect, reg, offset, len);
break;
case LOC_LOCAL:
case LOC_LOCAL_ARG:
- offset = SYMBOL_VALUE (sym);
- reg = FP_REGNUM;
+ reg = frame_regno;
+ offset = frame_offset + SYMBOL_VALUE (sym);
if (info_verbose)
{
- printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset %d from frame ptr reg %d\n",
- SYMBOL_NAME (sym), len, offset, reg);
+ printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
+ SYMBOL_NAME (sym), len);
+ printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
}
add_memrange (collect, reg, offset, len);
break;
/* Add all locals (or args) symbols to collection list */
static void
-add_local_symbols (collect, pc, type)
+add_local_symbols (collect, pc, frame_regno, frame_offset, type)
struct collection_list *collect;
CORE_ADDR pc;
+ long frame_regno;
+ long frame_offset;
int type;
{
struct symbol *sym;
if (type == 'L') /* collecting Locals */
{
count++;
- collect_symbol (collect, sym);
+ collect_symbol (collect, sym, frame_regno, frame_offset);
}
break;
case LOC_ARG:
if (type == 'A') /* collecting Arguments */
{
count++;
- collect_symbol (collect, sym);
+ collect_symbol (collect, sym, frame_regno, frame_offset);
}
}
}
struct collection_list *collect;
struct cmd_list_element *cmd;
struct agent_expr *aexpr;
+ long frame_reg, frame_offset;
+
clear_collection_list (&tracepoint_list);
clear_collection_list (&stepping_list);
*tdp_actions = NULL;
*stepping_actions = NULL;
+ TARGET_VIRTUAL_FRAME_POINTER (t->address, &frame_reg, &frame_offset);
+
for (action = t->actions; action; action = action->next)
{
QUIT; /* allow user to bail out with ^C */
}
else if (0 == strncasecmp ("$arg", action_exp, 4))
{
- add_local_symbols (collect, t->address, 'A');
+ add_local_symbols (collect,
+ t->address,
+ frame_reg,
+ frame_offset,
+ 'A');
action_exp = strchr (action_exp, ','); /* more? */
}
else if (0 == strncasecmp ("$loc", action_exp, 4))
{
- add_local_symbols (collect, t->address, 'L');
+ add_local_symbols (collect,
+ t->address,
+ frame_reg,
+ frame_offset,
+ 'L');
action_exp = strchr (action_exp, ','); /* more? */
}
else
struct agent_reqs areqs;
exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
-
- old_chain = make_cleanup (free_current_contents, &exp);
-
- aexpr = gen_trace_for_expr (exp);
-
- old_chain1 = make_cleanup (free_agent_expr, aexpr);
-
- ax_reqs (aexpr, &areqs);
- if (areqs.flaw != agent_flaw_none)
- error ("malformed expression");
-
- if (areqs.min_height < 0)
- error ("gdb: Internal error: expression has min height < 0");
- if (areqs.max_height > 20)
- error ("expression too complicated, try simplifying");
-
- discard_cleanups (old_chain1);
- add_aexpr (collect, aexpr);
-
- /* take care of the registers */
- if (areqs.reg_mask_len > 0)
- {
- int ndx1;
- int ndx2;
-
- for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
- {
- QUIT; /* allow user to bail out with ^C */
- if (areqs.reg_mask[ndx1] != 0)
- {
- /* assume chars have 8 bits */
- for (ndx2 = 0; ndx2 < 8; ndx2++)
- if (areqs.reg_mask[ndx1] & (1 << ndx2))
- /* it's used -- record it */
- add_register (collect, ndx1 * 8 + ndx2);
- }
- }
- }
+ old_chain = make_cleanup ((make_cleanup_func)
+ free_current_contents, &exp);
+
+ switch (exp->elts[0].opcode) {
+ case OP_REGISTER:
+ i = exp->elts[1].longconst;
+ if (info_verbose)
+ 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,
+ frame_reg,
+ frame_offset);
+ break;
+
+ default: /* full-fledged expression */
+ aexpr = gen_trace_for_expr (t->address, exp);
+
+ old_chain1 = make_cleanup ((make_cleanup_func)
+ free_agent_expr, aexpr);
+
+ ax_reqs (aexpr, &areqs);
+ if (areqs.flaw != agent_flaw_none)
+ error ("malformed expression");
+
+ if (areqs.min_height < 0)
+ error ("gdb: Internal error: expression has min height < 0");
+ if (areqs.max_height > 20)
+ error ("expression too complicated, try simplifying");
+
+ discard_cleanups (old_chain1);
+ add_aexpr (collect, aexpr);
+
+ /* take care of the registers */
+ if (areqs.reg_mask_len > 0)
+ {
+ int ndx1;
+ int ndx2;
+
+ for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ if (areqs.reg_mask[ndx1] != 0)
+ {
+ /* assume chars have 8 bits */
+ for (ndx2 = 0; ndx2 < 8; ndx2++)
+ if (areqs.reg_mask[ndx1] & (1 << ndx2))
+ /* it's used -- record it */
+ add_register (collect, ndx1 * 8 + ndx2);
+ }
+ }
+ }
+ break;
+ } /* switch */
do_cleanups (old_chain);
- }
+ } /* do */
} while (action_exp && *action_exp++ == ',');
- }
+ } /* if */
else if (cmd->function.cfunc == while_stepping_pseudocommand)
{
collect = &stepping_list;
else
break; /* end tracepoint actions */
}
- }
+ } /* for */
memrange_sortmerge (&tracepoint_list);
memrange_sortmerge (&stepping_list);
collect->next_aexpr_elt++;
}
-
static char target_buf[2048];
+/* Set "transparent" memory ranges
+
+ Allow trace mechanism to treat text-like sections
+ (and perhaps all read-only sections) transparently,
+ i.e. don't reject memory requests from these address ranges
+ just because they haven't been collected. */
+
+static void
+remote_set_transparent_ranges (void)
+{
+ extern bfd *exec_bfd;
+ asection *s;
+ bfd_size_type size;
+ bfd_vma lma;
+ int anysecs = 0;
+
+ if (!exec_bfd)
+ return; /* no information to give. */
+
+ strcpy (target_buf, "QTro");
+ for (s = exec_bfd->sections; s; s = s->next)
+ {
+ char tmp[40];
+
+ if ((s->flags & SEC_LOAD) == 0 ||
+ /* (s->flags & SEC_CODE) == 0 || */
+ (s->flags & SEC_READONLY) == 0)
+ continue;
+
+ anysecs = 1;
+ lma = s->lma;
+ size = bfd_get_section_size_before_reloc (s);
+ sprintf (tmp, ":%x,%x", lma, lma + size);
+ strcat (target_buf, tmp);
+ }
+ if (anysecs)
+ {
+ putpkt (target_buf);
+ getpkt (target_buf, 0);
+ }
+}
+
/* tstart command:
Tell target to clear any previous trace experiment.
do_cleanups (old_chain);
}
}
+ /* Tell target to treat text-like sections as transparent */
+ remote_set_transparent_ranges ();
+ /* Now insert traps and begin collecting data */
putpkt ("QTStart");
remote_get_noisy_reply (target_buf);
if (strcmp (target_buf, "OK"))
set_tracepoint_num (-1);
set_traceframe_context(-1);
trace_running_p = 1;
+ if (trace_start_stop_hook)
+ trace_start_stop_hook(1, from_tty);
+
}
else
error ("Trace can only be run on remote targets.");
if (strcmp (target_buf, "OK"))
error ("Bogus reply from target: %s", target_buf);
trace_running_p = 0;
+ if (trace_start_stop_hook)
+ trace_start_stop_hook(0, from_tty);
}
else
error ("Trace can only be run on remote targets.");
while (reply && *reply)
switch (*reply) {
case 'F':
- if ((target_frameno = strtol (++reply, &reply, 16)) == -1)
+ if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
{
/* A request for a non-existant trace frame has failed.
Our response will be different, depending on FROM_TTY:
}
break;
case 'T':
- if ((target_tracept = strtol (++reply, &reply, 16)) == -1)
+ if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
error ("Target failed to find requested trace frame.");
break;
case 'O': /* "OK"? */
{ /* STUB_COMM PART_IMPLEMENTED */
/* this should only be called with a numeric argument */
int frameno = -1;
- int target_frameno = -1, target_tracept = -1, target_stepfrm = 0;
char *tmp;
if (target_is_remote ())
{
+ if (trace_find_hook)
+ trace_find_hook (args, from_tty);
+
if (args == 0 || *args == 0)
{ /* TFIND with no args means find NEXT trace frame. */
if (traceframe_number == -1)
int from_tty;
{ /* STUB_COMM PART_IMPLEMENTED */
CORE_ADDR pc;
- int target_frameno;
char *tmp;
if (target_is_remote ())
char *args;
int from_tty;
{ /* STUB_COMM PART_IMPLEMENTED */
- int target_frameno, tdp;
+ int tdp;
char buf[40], *tmp;
if (target_is_remote ())
static CORE_ADDR start_pc, end_pc;
struct symtabs_and_lines sals;
struct symtab_and_line sal;
- int target_frameno;
char *tmp;
struct cleanup *old_chain;
int from_tty;
{ /* STUB_COMM PART_IMPLEMENTED */
static CORE_ADDR start, stop;
- int target_frameno;
char *tmp;
if (target_is_remote ())
int from_tty;
{ /* STUB_COMM PART_IMPLEMENTED */
CORE_ADDR start, stop;
- int target_frameno;
char *tmp;
if (target_is_remote ())
struct minimal_symbol *msym;
struct block *block;
char **canonical, *symname, *save_args = args;
- int i, nsyms, count = 0;
+ int i, j, nsyms, count = 0;
if (args == 0 || *args == 0)
error ("requires an argument (function, line or *addr) to define a scope");
case LOC_CONST_BYTES:
printf_filtered ("constant bytes: ");
if (SYMBOL_TYPE (sym))
- for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (sym)); i++)
+ for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++)
fprintf_filtered (gdb_stdout, " %02x",
- (unsigned) SYMBOL_VALUE_BYTES (sym) [i]);
+ (unsigned) SYMBOL_VALUE_BYTES (sym) [j]);
break;
case LOC_STATIC:
printf_filtered ("in static storage at address ");
break;
case LOC_REGISTER:
printf_filtered ("a local variable in register $%s",
- reg_names [SYMBOL_VALUE (sym)]);
+ REGISTER_NAME (SYMBOL_VALUE (sym)));
break;
case LOC_ARG:
case LOC_LOCAL_ARG:
break;
case LOC_REGPARM:
printf_filtered ("an argument in register $%s",
- reg_names[SYMBOL_VALUE (sym)]);
+ REGISTER_NAME (SYMBOL_VALUE (sym)));
break;
case LOC_REGPARM_ADDR:
printf_filtered ("the address of an argument, in register $%s",
- reg_names[SYMBOL_VALUE (sym)]);
+ REGISTER_NAME (SYMBOL_VALUE (sym)));
break;
case LOC_TYPEDEF:
printf_filtered ("a typedef.\n");
case LOC_BASEREG:
printf_filtered ("a variable at offset %d from register $%s",
SYMBOL_VALUE (sym),
- reg_names [SYMBOL_BASEREG (sym)]);
+ REGISTER_NAME (SYMBOL_BASEREG (sym)));
break;
case LOC_BASEREG_ARG:
printf_filtered ("an argument at offset %d from register $%s",
SYMBOL_VALUE (sym),
- reg_names [SYMBOL_BASEREG (sym)]);
+ REGISTER_NAME (SYMBOL_BASEREG (sym)));
break;
case LOC_UNRESOLVED:
msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);