gdb/
authorPedro Alves <palves@redhat.com>
Thu, 27 Jan 2011 21:39:24 +0000 (21:39 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 27 Jan 2011 21:39:24 +0000 (21:39 +0000)
* tracepoint.c (tfile_read): New.
(tfile_open): Use it.
(tfile_get_traceframe_address): Use it.
(tfile_trace_find): Use it.
(walk_blocks_callback_func): New typedef.
(match_blocktype): New function.
(traceframe_walk_blocks): New function.
(traceframe_find_block_type): New function.
(tfile_fetch_registers, tfile_xfer_partial)
(tfile_get_trace_state_variable_value): Use
traceframe_find_block_type and tfile_read.

gdb/ChangeLog
gdb/tracepoint.c

index 7c4ea3a..21e04d6 100644 (file)
@@ -1,3 +1,17 @@
+2011-01-27  Pedro Alves  <pedro@codesourcery.com>
+
+       * tracepoint.c (tfile_read): New.
+       (tfile_open): Use it.
+       (tfile_get_traceframe_address): Use it.
+       (tfile_trace_find): Use it.
+       (walk_blocks_callback_func): New typedef.
+       (match_blocktype): New function.
+       (traceframe_walk_blocks): New function.
+       (traceframe_find_block_type): New function.
+       (tfile_fetch_registers, tfile_xfer_partial)
+       (tfile_get_trace_state_variable_value): Use
+       traceframe_find_block_type and tfile_read.
+
 2011-01-26  Kevin Buettner  <kevinb@redhat.com>
 
        * remote-mips.c: Add internationalization mark ups.  Remove
index a078de4..b15f75d 100644 (file)
@@ -3212,6 +3212,24 @@ static void tfile_interp_line (char *line,
                               struct uploaded_tp **utpp,
                               struct uploaded_tsv **utsvp);
 
+/* Read SIZE bytes into READBUF from the trace frame, starting at
+   TRACE_FD's current position.  Note that this call `read'
+   underneath, hence it advances the file's seek position.  Throws an
+   error if the `read' syscall fails, or less than SIZE bytes are
+   read.  */
+
+static void
+tfile_read (gdb_byte *readbuf, int size)
+{
+  int gotten;
+
+  gotten = read (trace_fd, readbuf, size);
+  if (gotten < 0)
+    perror_with_name (trace_filename);
+  else if (gotten < size)
+    error (_("Premature end of file while reading trace file"));
+}
+
 static void
 tfile_open (char *filename, int from_tty)
 {
@@ -3222,7 +3240,7 @@ tfile_open (char *filename, int from_tty)
   char header[TRACE_HEADER_SIZE];
   char linebuf[1000]; /* Should be max remote packet size or so.  */
   char byte;
-  int bytes, i, gotten;
+  int bytes, i;
   struct trace_status *ts;
   struct uploaded_tp *uploaded_tps = NULL;
   struct uploaded_tsv *uploaded_tsvs = NULL;
@@ -3259,11 +3277,7 @@ tfile_open (char *filename, int from_tty)
 
   bytes = 0;
   /* Read the file header and test for validity.  */
-  gotten = read (trace_fd, &header, TRACE_HEADER_SIZE);
-  if (gotten < 0)
-    perror_with_name (trace_filename);
-  else if (gotten < TRACE_HEADER_SIZE)
-    error (_("Premature end of file while reading trace file"));
+  tfile_read ((gdb_byte *) &header, TRACE_HEADER_SIZE);
 
   bytes += TRACE_HEADER_SIZE;
   if (!(header[0] == 0x7f
@@ -3287,11 +3301,7 @@ tfile_open (char *filename, int from_tty)
   i = 0;
   while (1)
     {
-      gotten = read (trace_fd, &byte, 1);
-      if (gotten < 0)
-       perror_with_name (trace_filename);
-      else if (gotten < 1)
-       error (_("Premature end of file while reading trace file"));
+      tfile_read (&byte, 1);
 
       ++bytes;
       if (byte == '\n')
@@ -3679,17 +3689,12 @@ tfile_get_traceframe_address (off_t tframe_offset)
   short tpnum;
   struct breakpoint *tp;
   off_t saved_offset = cur_offset;
-  int gotten;
 
   /* FIXME dig pc out of collected registers.  */
 
   /* Fall back to using tracepoint address.  */
   lseek (trace_fd, tframe_offset, SEEK_SET);
-  gotten = read (trace_fd, &tpnum, 2);
-  if (gotten < 0)
-    perror_with_name (trace_filename);
-  else if (gotten < 2)
-    error (_("Premature end of file while reading trace file"));
+  tfile_read ((gdb_byte *) &tpnum, 2);
   tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
                                          gdbarch_byte_order
                                              (target_gdbarch));
@@ -3715,7 +3720,7 @@ tfile_trace_find (enum trace_find_type type, int num,
                  ULONGEST addr1, ULONGEST addr2, int *tpp)
 {
   short tpnum;
-  int tfnum = 0, found = 0, gotten;
+  int tfnum = 0, found = 0;
   unsigned int data_size;
   struct breakpoint *tp;
   off_t offset, tframe_offset;
@@ -3726,22 +3731,14 @@ tfile_trace_find (enum trace_find_type type, int num,
   while (1)
     {
       tframe_offset = offset;
-      gotten = read (trace_fd, &tpnum, 2);
-      if (gotten < 0)
-       perror_with_name (trace_filename);
-      else if (gotten < 2)
-       error (_("Premature end of file while reading trace file"));
+      tfile_read ((gdb_byte *) &tpnum, 2);
       tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
                                              gdbarch_byte_order
                                                  (target_gdbarch));
       offset += 2;
       if (tpnum == 0)
        break;
-      gotten = read (trace_fd, &data_size, 4); 
-      if (gotten < 0)
-       perror_with_name (trace_filename);
-      else if (gotten < 4)
-       error (_("Premature end of file while reading trace file"));
+      tfile_read ((gdb_byte *) &data_size, 4);
       data_size = (unsigned int) extract_unsigned_integer
                                      ((gdb_byte *) &data_size, 4,
                                      gdbarch_byte_order (target_gdbarch));
@@ -3795,6 +3792,90 @@ tfile_trace_find (enum trace_find_type type, int num,
   return -1;
 }
 
+/* Prototype of the callback passed to tframe_walk_blocks.  */
+typedef int (*walk_blocks_callback_func) (char blocktype, void *data);
+
+/* Callback for traceframe_walk_blocks, used to find a given block
+   type in a traceframe.  */
+
+static int
+match_blocktype (char blocktype, void *data)
+{
+  char *wantedp = data;
+
+  if (*wantedp == blocktype)
+    return 1;
+
+  return 0;
+}
+
+/* Walk over all traceframe block starting at POS offset from
+   CUR_OFFSET, and call CALLBACK for each block found, passing in DATA
+   unmodified.  If CALLBACK returns true, this returns the position in
+   the traceframe where the block is found, relative to the start of
+   the traceframe (cur_offset).  Returns -1 if no callback call
+   returned true, indicating that all blocks have been walked.  */
+
+static int
+traceframe_walk_blocks (walk_blocks_callback_func callback,
+                       int pos, void *data)
+{
+  /* Iterate through a traceframe's blocks, looking for a block of the
+     requested type.  */
+
+  lseek (trace_fd, cur_offset + pos, SEEK_SET);
+  while (pos < cur_data_size)
+    {
+      unsigned short mlen;
+      char block_type;
+
+      tfile_read (&block_type, 1);
+
+      ++pos;
+
+      if ((*callback) (block_type, data))
+       return pos;
+
+      switch (block_type)
+       {
+       case 'R':
+         lseek (trace_fd, cur_offset + pos + trace_regblock_size, SEEK_SET);
+         pos += trace_regblock_size;
+         break;
+       case 'M':
+         lseek (trace_fd, cur_offset + pos + 8, SEEK_SET);
+         tfile_read ((gdb_byte *) &mlen, 2);
+          mlen = (unsigned short)
+                extract_unsigned_integer ((gdb_byte *) &mlen, 2,
+                                          gdbarch_byte_order
+                                              (target_gdbarch));
+         lseek (trace_fd, mlen, SEEK_CUR);
+         pos += (8 + 2 + mlen);
+         break;
+       case 'V':
+         lseek (trace_fd, cur_offset + pos + 4 + 8, SEEK_SET);
+         pos += (4 + 8);
+         break;
+       default:
+         error ("Unknown block type '%c' (0x%x) in trace frame",
+                block_type, block_type);
+         break;
+       }
+    }
+
+  return -1;
+}
+
+/* Convenience wrapper around traceframe_walk_blocks.  Looks for the
+   position offset of a block of type TYPE_WANTED in the current trace
+   frame, starting at POS.  Returns -1 if no such block was found.  */
+
+static int
+traceframe_find_block_type (char type_wanted, int pos)
+{
+  return traceframe_walk_blocks (match_blocktype, pos, &type_wanted);
+}
+
 /* Look for a block of saved registers in the traceframe, and get the
    requested register from it.  */
 
@@ -3804,7 +3885,7 @@ tfile_fetch_registers (struct target_ops *ops,
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   char block_type;
-  int pos, offset, regn, regsize, gotten, pc_regno;
+  int pos, offset, regn, regsize, pc_regno;
   unsigned short mlen;
   char *regs;
 
@@ -3815,79 +3896,38 @@ tfile_fetch_registers (struct target_ops *ops,
 
   regs = alloca (trace_regblock_size);
 
-  lseek (trace_fd, cur_offset, SEEK_SET);
-  pos = 0;
-  while (pos < cur_data_size)
+  if (traceframe_find_block_type ('R', 0) >= 0)
     {
-      gotten = read (trace_fd, &block_type, 1);
-      if (gotten < 0)
-       perror_with_name (trace_filename);
-      else if (gotten < 1)
-       error (_("Premature end of file while reading trace file"));
+      tfile_read (regs, trace_regblock_size);
 
-      ++pos;
-      switch (block_type)
+      /* Assume the block is laid out in GDB register number order,
+        each register with the size that it has in GDB.  */
+      offset = 0;
+      for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
        {
-       case 'R':
-         gotten = read (trace_fd, regs, trace_regblock_size);
-         if (gotten < 0)
-           perror_with_name (trace_filename);
-         else if (gotten < trace_regblock_size)
-           error (_("Premature end of file while reading trace file"));
-
-         /* Assume the block is laid out in GDB register number order,
-            each register with the size that it has in GDB.  */
-         offset = 0;
-         for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
+         regsize = register_size (gdbarch, regn);
+         /* Make sure we stay within block bounds.  */
+         if (offset + regsize >= trace_regblock_size)
+           break;
+         if (regcache_register_status (regcache, regn) == REG_UNKNOWN)
            {
-             regsize = register_size (gdbarch, regn);
-             /* Make sure we stay within block bounds.  */
-             if (offset + regsize >= trace_regblock_size)
-               break;
-             if (regcache_register_status (regcache, regn) == REG_UNKNOWN)
+             if (regno == regn)
                {
-                 if (regno == regn)
-                   {
-                     regcache_raw_supply (regcache, regno, regs + offset);
-                     break;
-                   }
-                 else if (regno == -1)
-                   {
-                     regcache_raw_supply (regcache, regn, regs + offset);
-                   }
+                 regcache_raw_supply (regcache, regno, regs + offset);
+                 break;
+               }
+             else if (regno == -1)
+               {
+                 regcache_raw_supply (regcache, regn, regs + offset);
                }
-             offset += regsize;
            }
-         return;
-       case 'M':
-         lseek (trace_fd, 8, SEEK_CUR);
-         gotten = read (trace_fd, &mlen, 2);
-         if (gotten < 0)
-           perror_with_name (trace_filename);
-         else if (gotten < 2)
-           error (_("Premature end of file while reading trace file"));
-          mlen = (unsigned short)
-                extract_unsigned_integer ((gdb_byte *) &mlen, 2,
-                                          gdbarch_byte_order
-                                              (target_gdbarch));
-         lseek (trace_fd, mlen, SEEK_CUR);
-         pos += (8 + 2 + mlen);
-         break;
-       case 'V':
-         lseek (trace_fd, 4 + 8, SEEK_CUR);
-         pos += (4 + 8);
-         break;
-       default:
-         error (_("Unknown block type '%c' (0x%x) in trace frame"),
-                block_type, block_type);
-         break;
+         offset += regsize;
        }
+      return;
     }
 
-  /* We get here if no register data has been found.  Although we
-     don't like making up numbers, GDB has all manner of troubles when
-     the target says some register is not available.  Filling in with
-     zeroes is a reasonable fallback.  */
+  /* We get here if no register data has been found.  Mark registers
+     as unavailable.  */
   for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
     regcache_raw_supply (regcache, regn, NULL);
 
@@ -3930,10 +3970,7 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
                    const char *annex, gdb_byte *readbuf,
                    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
 {
-  char block_type;
-  int pos, gotten;
-  ULONGEST maddr, amt;
-  unsigned short mlen;
+  int pos;
 
   /* We're only doing regular memory for now.  */
   if (object != TARGET_OBJECT_MEMORY)
@@ -3942,72 +3979,36 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
   if (readbuf == NULL)
     error (_("tfile_xfer_partial: trace file is read-only"));
 
-  lseek (trace_fd, cur_offset, SEEK_SET);
+  /* Iterate through the traceframe's blocks, looking for memory.  */
   pos = 0;
-  while (pos < cur_data_size)
+  while ((pos = traceframe_find_block_type ('M', pos)) >= 0)
     {
-      gotten = read (trace_fd, &block_type, 1);
-      if (gotten < 0)
-       perror_with_name (trace_filename);
-      else if (gotten < 1)
-       error (_("Premature end of file while reading trace file"));
-      ++pos;
-      switch (block_type)
+      ULONGEST maddr, amt;
+      unsigned short mlen;
+
+      tfile_read ((gdb_byte *) &maddr, 8);
+      maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
+                                       gdbarch_byte_order (target_gdbarch));
+      tfile_read ((gdb_byte *) &mlen, 2);
+      mlen = (unsigned short)
+       extract_unsigned_integer ((gdb_byte *) &mlen, 2,
+                                 gdbarch_byte_order (target_gdbarch));
+
+      /* If the block includes the first part of the desired range,
+        return as much it has; GDB will re-request the remainder,
+        which might be in a different block of this trace frame.  */
+      if (maddr <= offset && offset < (maddr + mlen))
        {
-       case 'R':
-         lseek (trace_fd, trace_regblock_size, SEEK_CUR);
-         pos += trace_regblock_size;
-         break;
-       case 'M':
-         gotten = read (trace_fd, &maddr, 8);
-         if (gotten < 0)
-           perror_with_name (trace_filename);
-         else if (gotten < 8)
-           error (_("Premature end of file while reading trace file"));
-          maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
-                                           gdbarch_byte_order
-                                               (target_gdbarch));
-         gotten = read (trace_fd, &mlen, 2);
-         if (gotten < 0)
-           perror_with_name (trace_filename);
-         else if (gotten < 2)
-           error (_("Premature end of file while reading trace file"));
-          mlen = (unsigned short)
-                extract_unsigned_integer ((gdb_byte *) &mlen, 2,
-                                          gdbarch_byte_order
-                                              (target_gdbarch));
-         /* If the block includes the first part of the desired
-            range, return as much it has; GDB will re-request the
-            remainder, which might be in a different block of this
-            trace frame.  */
-         if (maddr <= offset && offset < (maddr + mlen))
-           {
-             amt = (maddr + mlen) - offset;
-             if (amt > len)
-               amt = len;
+         amt = (maddr + mlen) - offset;
+         if (amt > len)
+           amt = len;
 
-             gotten = read (trace_fd, readbuf, amt);
-             if (gotten < 0)
-               perror_with_name (trace_filename);
-             /* While it's acceptable to return less than was
-                originally asked for, it's not acceptable to return
-                less than what this block claims to contain.  */
-             else if (gotten < amt)
-               error (_("Premature end of file while reading trace file"));
-             return amt;
-           }
-         lseek (trace_fd, mlen, SEEK_CUR);
-         pos += (8 + 2 + mlen);
-         break;
-       case 'V':
-         lseek (trace_fd, 4 + 8, SEEK_CUR);
-         pos += (4 + 8);
-         break;
-       default:
-         error (_("Unknown block type '%c' (0x%x) in traceframe"),
-                block_type, block_type);
-         break;
+         tfile_read (readbuf, amt);
+         return amt;
        }
+
+      /* Skip over this block.  */
+      pos += (8 + 2 + mlen);
     }
 
   /* It's unduly pedantic to refuse to look at the executable for
@@ -4022,14 +4023,16 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
 
       for (s = exec_bfd->sections; s; s = s->next)
        {
-         if ((s->flags & SEC_LOAD) == 0 ||
-             (s->flags & SEC_READONLY) == 0)
+         if ((s->flags & SEC_LOAD) == 0
+             || (s->flags & SEC_READONLY) == 0)
            continue;
 
          vma = s->vma;
          size = bfd_get_section_size (s);
          if (vma <= offset && offset < (vma + size))
            {
+             ULONGEST amt;
+
              amt = (vma + size) - offset;
              if (amt > len)
                amt = len;
@@ -4051,70 +4054,28 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
 static int
 tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val)
 {
-  char block_type;
-  int pos, vnum, gotten;
-  unsigned short mlen;
+  int pos;
 
-  lseek (trace_fd, cur_offset, SEEK_SET);
   pos = 0;
-  while (pos < cur_data_size)
+  while ((pos = traceframe_find_block_type ('V', pos)) >= 0)
     {
-      gotten = read (trace_fd, &block_type, 1);
-      if (gotten < 0)
-       perror_with_name (trace_filename);
-      else if (gotten < 1)
-       error (_("Premature end of file while reading trace file"));
-      ++pos;
-      switch (block_type)
-       {
-       case 'R':
-         lseek (trace_fd, trace_regblock_size, SEEK_CUR);
-         pos += trace_regblock_size;
-         break;
-       case 'M':
-         lseek (trace_fd, 8, SEEK_CUR);
-         gotten = read (trace_fd, &mlen, 2);
-         if (gotten < 0)
-           perror_with_name (trace_filename);
-         else if (gotten < 2)
-           error (_("Premature end of file while reading trace file"));
-          mlen = (unsigned short)
-                extract_unsigned_integer ((gdb_byte *) &mlen, 2,
+      int vnum;
+
+      tfile_read ((gdb_byte *) &vnum, 4);
+      vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4,
                                           gdbarch_byte_order
-                                              (target_gdbarch));
-         lseek (trace_fd, mlen, SEEK_CUR);
-         pos += (8 + 2 + mlen);
-         break;
-       case 'V':
-         gotten = read (trace_fd, &vnum, 4);
-         if (gotten < 0)
-           perror_with_name (trace_filename);
-         else if (gotten < 4)
-           error (_("Premature end of file while reading trace file"));
-          vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4,
-                                              gdbarch_byte_order
-                                                  (target_gdbarch));
-         if (tsvnum == vnum)
-           {
-             gotten = read (trace_fd, val, 8);
-             if (gotten < 0)
-               perror_with_name (trace_filename);
-             else if (gotten < 8)
-               error (_("Premature end of file while reading trace file"));
-              *val = extract_signed_integer ((gdb_byte *)val, 8,
-                                            gdbarch_byte_order
-                                                (target_gdbarch));
-             return 1;
-           }
-         lseek (trace_fd, 8, SEEK_CUR);
-         pos += (4 + 8);
-         break;
-       default:
-         error (_("Unknown block type '%c' (0x%x) in traceframe"),
-                block_type, block_type);
-         break;
+                                          (target_gdbarch));
+      if (tsvnum == vnum)
+       {
+         tfile_read ((gdb_byte *) val, 8);
+         *val = extract_signed_integer ((gdb_byte *) val, 8,
+                                        gdbarch_byte_order
+                                        (target_gdbarch));
+         return 1;
        }
+      pos += (4 + 8);
     }
+
   /* Didn't find anything.  */
   return 0;
 }