/* 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
- {
- if (sal.symtab->dirname == NULL)
- {
- t->source_file = (char *) xmalloc (strlen (sal.symtab->filename) + 1);
- strcpy (t->source_file, sal.symtab->filename);
- }
- 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_REF_ARG:
printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
SYMBOL_NAME (sym));
break;
case LOC_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",
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",
/* 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);
+ old_chain = make_cleanup ((make_cleanup_func)
+ free_current_contents, &exp);
switch (exp->elts[0].opcode) {
case OP_REGISTER:
break;
case OP_VAR_VALUE:
- collect_symbol (collect, exp->elts[2].symbol);
+ collect_symbol (collect,
+ exp->elts[2].symbol,
+ frame_reg,
+ frame_offset);
break;
default: /* full-fledged expression */
- aexpr = gen_trace_for_expr (exp);
+ aexpr = gen_trace_for_expr (t->address, exp);
- old_chain1 = make_cleanup (free_agent_expr, aexpr);
+ old_chain1 = make_cleanup ((make_cleanup_func)
+ free_agent_expr, aexpr);
ax_reqs (aexpr, &areqs);
if (areqs.flaw != agent_flaw_none)
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);