diff options
-rw-r--r-- | gdb/ChangeLog | 14 | ||||
-rw-r--r-- | gdb/tracepoint.c | 395 |
2 files changed, 192 insertions, 217 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7c4ea3a6ec9..21e04d660dc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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 diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index a078de4b3f4..b15f75da875 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -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; } |