/* Trace file TFILE format support in GDB.
- Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ Copyright (C) 1997-2015 Free Software Foundation, Inc.
This file is part of GDB.
tfile_trace_file_writer_new (void)
{
struct tfile_trace_file_writer *writer
- = xmalloc (sizeof (struct tfile_trace_file_writer));
+ = XNEW (struct tfile_trace_file_writer);
writer->base.ops = &tfile_write_ops;
writer->fp = NULL;
}
static void
-tfile_open (char *filename, int from_tty)
+tfile_open (const char *arg, int from_tty)
{
- volatile struct gdb_exception ex;
char *temp;
struct cleanup *old_chain;
int flags;
struct trace_status *ts;
struct uploaded_tp *uploaded_tps = NULL;
struct uploaded_tsv *uploaded_tsvs = NULL;
+ char *filename;
target_preopen (from_tty);
- if (!filename)
+ if (!arg)
error (_("No trace file specified."));
- filename = tilde_expand (filename);
+ filename = tilde_expand (arg);
if (!IS_ABSOLUTE_PATH(filename))
{
temp = concat (current_directory, "/", filename, (char *) NULL);
bytes += TRACE_HEADER_SIZE;
if (!(header[0] == 0x7f
- && (strncmp (header + 1, "TRACE0\n", 7) == 0)))
+ && (startswith (header + 1, "TRACE0\n"))))
error (_("File is not a valid trace file."));
push_target (&tfile_ops);
ts->disconnected_tracing = 0;
ts->circular_buffer = 0;
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ TRY
{
/* Read through a section of newline-terminated lines that
define things like tracepoints. */
if (trace_regblock_size == 0)
error (_("No register block size recorded in trace file"));
}
- if (ex.reason < 0)
+ CATCH (ex, RETURN_MASK_ALL)
{
/* Remove the partially set up target. */
unpush_target (&tfile_ops);
throw_exception (ex);
}
+ END_CATCH
inferior_appeared (current_inferior (), TFILE_PID);
inferior_ptid = pid_to_ptid (TFILE_PID);
{
char *p = line;
- if (strncmp (p, "R ", strlen ("R ")) == 0)
+ if (startswith (p, "R "))
{
p += strlen ("R ");
trace_regblock_size = strtol (p, &p, 16);
}
- else if (strncmp (p, "status ", strlen ("status ")) == 0)
+ else if (startswith (p, "status "))
{
p += strlen ("status ");
parse_trace_status (p, current_trace_status ());
}
- else if (strncmp (p, "tp ", strlen ("tp ")) == 0)
+ else if (startswith (p, "tp "))
{
p += strlen ("tp ");
parse_tracepoint_definition (p, utpp);
}
- else if (strncmp (p, "tsv ", strlen ("tsv ")) == 0)
+ else if (startswith (p, "tsv "))
{
p += strlen ("tsv ");
parse_tsv_definition (p, utsvp);
struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
- int offset, regn, regsize, pc_regno;
- gdb_byte *regs;
+ int offset, regn, regsize;
/* An uninitialized reg size says we're not going to be
successful at getting register blocks. */
if (!trace_regblock_size)
return;
- regs = alloca (trace_regblock_size);
-
if (traceframe_find_block_type ('R', 0) >= 0)
{
+ gdb_byte *regs = alloca (trace_regblock_size);
+
tfile_read (regs, trace_regblock_size);
/* Assume the block is laid out in GDB register number order,
}
offset += regsize;
}
- return;
- }
-
- /* 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);
-
- /* We can often usefully guess that the PC is going to be the same
- as the address of the tracepoint. */
- pc_regno = gdbarch_pc_regnum (gdbarch);
-
- /* XXX This guessing code below only works if the PC register isn't
- a pseudo-register. The value of a pseudo-register isn't stored
- in the (non-readonly) regcache -- instead it's recomputed
- (probably from some other cached raw register) whenever the
- register is read. This guesswork should probably move to some
- higher layer. */
- if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
- return;
-
- if (regno == -1 || regno == pc_regno)
- {
- struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
-
- if (tp && tp->base.loc)
- {
- /* But don't try to guess if tracepoint is multi-location... */
- if (tp->base.loc->next)
- {
- warning (_("Tracepoint %d has multiple "
- "locations, cannot infer $pc"),
- tp->base.number);
- return;
- }
- /* ... or does while-stepping. */
- if (tp->step_count > 0)
- {
- warning (_("Tracepoint %d does while-stepping, "
- "cannot infer $pc"),
- tp->base.number);
- return;
- }
-
- store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
- gdbarch_byte_order (gdbarch),
- tp->base.loc->address);
- regcache_raw_supply (regcache, pc_regno, regs);
- }
}
+ else
+ tracefile_fetch_registers (regcache, regno);
}
static enum target_xfer_status
if (get_traceframe_number () != -1)
{
int pos = 0;
+ enum target_xfer_status res;
+ /* Records the lowest available address of all blocks that
+ intersects the requested range. */
+ ULONGEST low_addr_available = 0;
/* Iterate through the traceframe's blocks, looking for
memory. */
return TARGET_XFER_OK;
}
+ if (offset < maddr && maddr < (offset + len))
+ if (low_addr_available == 0 || low_addr_available > maddr)
+ low_addr_available = maddr;
+
/* Skip over this block. */
pos += (8 + 2 + mlen);
}
- return exec_read_partial_read_only (readbuf, offset, len, xfered_len);
+ /* Requested memory is unavailable in the context of traceframes,
+ 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);
+ res = exec_read_partial_read_only (readbuf, offset, len, xfered_len);
+
+ if (res == TARGET_XFER_OK)
+ return TARGET_XFER_OK;
+ else
+ {
+ /* No use trying further, we know some memory starting
+ at MEMADDR isn't available. */
+ *xfered_len = len;
+ return TARGET_XFER_UNAVAILABLE;
+ }
}
else
{