Not part of the sources
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
index fa5ac4db38d1de04f15956b456b48b2823fb5810..9f036178bd1c9e18949ef25e215ddcd31a7abe5a 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
 
@@ -33,8 +33,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #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
@@ -332,22 +332,11 @@ set_raw_tracepoint (sal)
   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;
@@ -489,13 +478,13 @@ tracepoints_info (tpnum_exp, from_tty)
                         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);
@@ -839,7 +828,7 @@ read_actions (t)
   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
@@ -961,7 +950,8 @@ validate_actionline (line, t)
            /* 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)
@@ -980,8 +970,8 @@ validate_actionline (line, t)
 
        /* 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");
@@ -1167,9 +1157,11 @@ add_memrange (memranges, type, base, len)
 
 /* 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;
@@ -1198,31 +1190,48 @@ collect_symbol (collect, sym)
     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;
@@ -1249,9 +1258,11 @@ collect_symbol (collect, sym)
 
 /* 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;
@@ -1274,7 +1285,7 @@ add_local_symbols (collect, pc, type)
            if (type == 'L')    /* collecting Locals */
              {
                count++;
-               collect_symbol (collect, sym);
+               collect_symbol (collect, sym, frame_regno, frame_offset);
              }
            break;
          case LOC_ARG:
@@ -1286,7 +1297,7 @@ add_local_symbols (collect, pc, type)
            if (type == 'A')    /* collecting Arguments */
              {
                count++;
-               collect_symbol (collect, sym);
+               collect_symbol (collect, sym, frame_regno, frame_offset);
              }
          }
        }
@@ -1444,6 +1455,8 @@ encode_actions (t, tdp_actions, stepping_actions)
   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);
@@ -1452,6 +1465,8 @@ encode_actions (t, tdp_actions, stepping_actions)
   *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 */
@@ -1481,12 +1496,20 @@ encode_actions (t, tdp_actions, stepping_actions)
              }
            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
@@ -1497,48 +1520,75 @@ encode_actions (t, tdp_actions, stepping_actions)
                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;
@@ -1550,7 +1600,7 @@ encode_actions (t, tdp_actions, stepping_actions)
          else
            break;                      /* end tracepoint actions */
        }
-    }
+    }                  /* for */
   memrange_sortmerge (&tracepoint_list); 
   memrange_sortmerge (&stepping_list); 
 
@@ -1574,9 +1624,50 @@ add_aexpr(collect, aexpr)
   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.
@@ -1665,6 +1756,9 @@ trace_start_command (args, from_tty)
              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"))
@@ -1673,6 +1767,9 @@ trace_start_command (args, from_tty)
       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.");
@@ -1691,6 +1788,8 @@ trace_stop_command (args, from_tty)
       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.");
@@ -1740,7 +1839,7 @@ finish_tfind_command (msg, from_tty)
   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:
@@ -1777,7 +1876,7 @@ finish_tfind_command (msg, 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"? */
@@ -1849,11 +1948,13 @@ trace_find_command (args, from_tty)
 { /* 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)
@@ -1917,7 +2018,6 @@ trace_find_pc_command (args, from_tty)
      int from_tty;
 { /* STUB_COMM PART_IMPLEMENTED */
   CORE_ADDR pc;
-  int target_frameno;
   char *tmp;
 
   if (target_is_remote ())
@@ -1940,7 +2040,7 @@ trace_find_tracepoint_command (args, from_tty)
      char *args;
      int from_tty;
 { /* STUB_COMM PART_IMPLEMENTED */
-  int target_frameno, tdp;
+  int tdp;
   char buf[40], *tmp;
 
   if (target_is_remote ())
@@ -1976,7 +2076,6 @@ trace_find_line_command (args, from_tty)
   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;
 
@@ -2063,7 +2162,6 @@ trace_find_range_command (args, from_tty)
      int from_tty;
 { /* STUB_COMM PART_IMPLEMENTED */
   static CORE_ADDR start, stop;
-  int target_frameno;
   char *tmp;
 
   if (target_is_remote ())
@@ -2102,7 +2200,6 @@ trace_find_outside_command (args, from_tty)
      int from_tty;
 { /* STUB_COMM PART_IMPLEMENTED */
   CORE_ADDR start, stop;
-  int target_frameno;
   char *tmp;
 
   if (target_is_remote ())
@@ -2213,7 +2310,7 @@ scope_info (args, from_tty)
   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");
@@ -2256,9 +2353,9 @@ scope_info (args, from_tty)
          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 ");
@@ -2266,7 +2363,7 @@ scope_info (args, from_tty)
            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:
@@ -2283,11 +2380,11 @@ scope_info (args, from_tty)
            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");
@@ -2304,12 +2401,12 @@ scope_info (args, from_tty)
          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);
This page took 0.032551 seconds and 4 git commands to generate.