X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftracefile-tfile.c;h=57bb597f4f3ceb1e250f76e973bd1ae1aaa93e09;hb=ec8f76882145c71bef81a9cadf0bf51ff9fa5b35;hp=68ff5b14b79ac0cf7ed81fd71ff9a75df3264a91;hpb=224c3ddb89a43bf8db06c373d4ff429477833c0f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c index 68ff5b14b7..57bb597f4f 100644 --- a/gdb/tracefile-tfile.c +++ b/gdb/tracefile-tfile.c @@ -1,6 +1,6 @@ /* Trace file TFILE format support in GDB. - Copyright (C) 1997-2015 Free Software Foundation, Inc. + Copyright (C) 1997-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -28,6 +28,11 @@ #include "exec.h" /* exec_bfd */ #include "completer.h" #include "filenames.h" +#include "remote.h" +#include "xml-tdesc.h" +#include "target-descriptions.h" +#include "buffer.h" +#include #ifndef O_LARGEFILE #define O_LARGEFILE 0 @@ -262,6 +267,42 @@ tfile_write_uploaded_tp (struct trace_file_writer *self, sizeof (utp->traceframe_usage))); } +/* This is the implementation of trace_file_write_ops method + write_tdesc. */ + +static void +tfile_write_tdesc (struct trace_file_writer *self) +{ + struct tfile_trace_file_writer *writer + = (struct tfile_trace_file_writer *) self; + char *tdesc = target_fetch_description_xml (¤t_target); + char *ptr = tdesc; + char *next; + + if (tdesc == NULL) + return; + + /* Write tdesc line by line, prefixing each line with "tdesc ". */ + while (ptr != NULL) + { + next = strchr (ptr, '\n'); + if (next != NULL) + { + fprintf (writer->fp, "tdesc %.*s\n", (int) (next - ptr), ptr); + /* Skip the \n. */ + next++; + } + else if (*ptr != '\0') + { + /* Last line, doesn't have a newline. */ + fprintf (writer->fp, "tdesc %s\n", ptr); + } + ptr = next; + } + + xfree (tdesc); +} + /* This is the implementation of trace_file_write_ops method write_definition_end. */ @@ -315,6 +356,7 @@ static const struct trace_file_write_ops tfile_write_ops = tfile_write_status, tfile_write_uploaded_tsv, tfile_write_uploaded_tp, + tfile_write_tdesc, tfile_write_definition_end, tfile_write_raw_data, NULL, @@ -352,7 +394,9 @@ static off_t trace_frames_offset; static off_t cur_offset; static int cur_data_size; int trace_regblock_size; +static struct buffer trace_tdesc; +static void tfile_append_tdesc_line (const char *line); static void tfile_interp_line (char *line, struct uploaded_tp **utpp, struct uploaded_tsv **utsvp); @@ -419,6 +463,9 @@ tfile_open (const char *arg, int from_tty) trace_filename = xstrdup (filename); trace_fd = scratch_chan; + /* Make sure this is clear. */ + buffer_free (&trace_tdesc); + bytes = 0; /* Read the file header and test for validity. */ tfile_read ((gdb_byte *) &header, TRACE_HEADER_SIZE); @@ -467,6 +514,9 @@ tfile_open (const char *arg, int from_tty) error (_("Excessively long lines in trace file")); } + /* By now, tdesc lines have been read from tfile - let's parse them. */ + target_find_description (); + /* Record the starting offset of the binary trace data. */ trace_frames_offset = bytes; @@ -530,6 +580,11 @@ tfile_interp_line (char *line, struct uploaded_tp **utpp, p += strlen ("tsv "); parse_tsv_definition (p, utsvp); } + else if (startswith (p, "tdesc ")) + { + p += strlen ("tdesc "); + tfile_append_tdesc_line (p); + } else warning (_("Ignoring trace file definition \"%s\""), line); } @@ -552,6 +607,7 @@ tfile_close (struct target_ops *self) trace_fd = -1; xfree (trace_filename); trace_filename = NULL; + buffer_free (&trace_tdesc); trace_reset_local_state (); } @@ -713,7 +769,7 @@ typedef int (*walk_blocks_callback_func) (char blocktype, void *data); static int match_blocktype (char blocktype, void *data) { - char *wantedp = data; + char *wantedp = (char *) data; if (*wantedp == blocktype) return 1; @@ -796,7 +852,7 @@ tfile_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regno) { struct gdbarch *gdbarch = get_regcache_arch (regcache); - int offset, regn, regsize; + int offset, regn, regsize, dummy; /* An uninitialized reg size says we're not going to be successful at getting register blocks. */ @@ -809,14 +865,15 @@ tfile_fetch_registers (struct target_ops *ops, tfile_read (regs, trace_regblock_size); - /* 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++) { + if (!remote_register_number_and_offset (get_regcache_arch (regcache), + regn, &dummy, &offset)) + continue; + regsize = register_size (gdbarch, regn); /* Make sure we stay within block bounds. */ - if (offset + regsize >= trace_regblock_size) + if (offset + regsize > trace_regblock_size) break; if (regcache_register_status (regcache, regn) == REG_UNKNOWN) { @@ -830,20 +887,49 @@ tfile_fetch_registers (struct target_ops *ops, regcache_raw_supply (regcache, regn, regs + offset); } } - offset += regsize; } } else tracefile_fetch_registers (regcache, regno); } +static enum target_xfer_status +tfile_xfer_partial_features (struct target_ops *ops, const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, + ULONGEST *xfered_len) +{ + if (strcmp (annex, "target.xml")) + return TARGET_XFER_E_IO; + + if (readbuf == NULL) + error (_("tfile_xfer_partial: tdesc is read-only")); + + if (trace_tdesc.used_size == 0) + return TARGET_XFER_E_IO; + + if (offset >= trace_tdesc.used_size) + return TARGET_XFER_EOF; + + if (len > trace_tdesc.used_size - offset) + len = trace_tdesc.used_size - offset; + + memcpy (readbuf, trace_tdesc.buffer + offset, len); + *xfered_len = len; + + return TARGET_XFER_OK; +} + static enum target_xfer_status tfile_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { - /* We're only doing regular memory for now. */ + /* We're only doing regular memory and tdesc for now. */ + if (object == TARGET_OBJECT_AVAILABLE_FEATURES) + return tfile_xfer_partial_features (ops, annex, readbuf, writebuf, + offset, len, xfered_len); if (object != TARGET_OBJECT_MEMORY) return TARGET_XFER_E_IO; @@ -902,7 +988,7 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object, and this address falls within a read-only section, fallback to reading from executable, up to LOW_ADDR_AVAILABLE. */ if (offset < low_addr_available) - len = min (len, low_addr_available - offset); + len = std::min (len, low_addr_available - offset); res = exec_read_partial_read_only (readbuf, offset, len, xfered_len); if (res == TARGET_XFER_OK) @@ -966,7 +1052,7 @@ tfile_get_trace_state_variable_value (struct target_ops *self, static int build_traceframe_info (char blocktype, void *data) { - struct traceframe_info *info = data; + struct traceframe_info *info = (struct traceframe_info *) data; switch (blocktype) { @@ -1023,6 +1109,16 @@ tfile_traceframe_info (struct target_ops *self) return info; } +/* Handles tdesc lines from tfile by appending the payload to + a global trace_tdesc variable. */ + +static void +tfile_append_tdesc_line (const char *line) +{ + buffer_grow_str (&trace_tdesc, line); + buffer_grow_str (&trace_tdesc, "\n"); +} + static void init_tfile_ops (void) {