/* CTF format support.
- Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Copyright (C) 2012-2015 Free Software Foundation, Inc.
Contributed by Hui Zhu <hui_zhu@mentor.com>
Contributed by Yao Qi <yao@codesourcery.com>
/* Write metadata in FORMAT. */
+static void
+ctf_save_write_metadata (struct trace_write_handler *handler,
+ const char *format, ...)
+ ATTRIBUTE_PRINTF (2, 3);
+
static void
ctf_save_write_metadata (struct trace_write_handler *handler,
const char *format, ...)
self->ops->frame_ops->end (self);
}
-/* The minimal file size of data stream. It is required by
- babeltrace. */
-
-#define CTF_FILE_MIN_SIZE 4096
-
/* This is the implementation of trace_file_write_ops method
end. */
struct ctf_trace_file_writer *writer = (struct ctf_trace_file_writer *) self;
gdb_assert (writer->tcs.content_size == 0);
- /* The babeltrace requires or assumes that the size of datastream
- file is greater than 4096 bytes. If we don't generate enough
- packets and events, create a fake packet which has zero event,
- to use up the space. */
- if (writer->tcs.packet_start < CTF_FILE_MIN_SIZE)
- {
- uint32_t u32;
-
- /* magic. */
- u32 = CTF_MAGIC;
- ctf_save_write_uint32 (&writer->tcs, u32);
-
- /* content_size. */
- u32 = 0;
- ctf_save_write_uint32 (&writer->tcs, u32);
-
- /* packet_size. */
- u32 = 12;
- if (writer->tcs.packet_start + u32 < CTF_FILE_MIN_SIZE)
- u32 = CTF_FILE_MIN_SIZE - writer->tcs.packet_start;
-
- u32 *= TARGET_CHAR_BIT;
- ctf_save_write_uint32 (&writer->tcs, u32);
-
- /* tpnum. */
- u32 = 0;
- ctf_save_write (&writer->tcs, (gdb_byte *) &u32, 2);
-
- /* Enlarge the file to CTF_FILE_MIN_SIZE is it is still less
- than that. */
- if (CTF_FILE_MIN_SIZE
- > (writer->tcs.packet_start + writer->tcs.content_size))
- {
- gdb_byte b = 0;
-
- /* Fake the content size to avoid assertion failure in
- ctf_save_fseek. */
- writer->tcs.content_size = (CTF_FILE_MIN_SIZE
- - 1 - writer->tcs.packet_start);
- ctf_save_fseek (&writer->tcs, CTF_FILE_MIN_SIZE - 1,
- SEEK_SET);
- ctf_save_write (&writer->tcs, &b, 1);
- }
- }
}
/* This is the implementation of trace_frame_write_ops method
struct trace_file_writer *
ctf_trace_file_writer_new (void)
{
- struct ctf_trace_file_writer *writer
- = xmalloc (sizeof (struct ctf_trace_file_writer));
+ struct ctf_trace_file_writer *writer = XNEW (struct ctf_trace_file_writer);
writer->base.ops = &ctf_write_ops;
/* Open CTF trace data in DIRNAME. */
static void
-ctf_open_dir (char *dirname)
+ctf_open_dir (const char *dirname)
{
struct bt_iter_pos begin_pos;
struct bt_iter_pos *pos;
second packet which contains events on trace blocks. */
static void
-ctf_open (char *dirname, int from_tty)
+ctf_open (const char *dirname, int from_tty)
{
struct bt_ctf_event *event;
uint32_t event_id;
struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
- int offset, regn, regsize, pc_regno;
- gdb_byte *regs = NULL;
struct bt_ctf_event *event = NULL;
struct bt_iter_pos *pos;
if (event != NULL)
{
+ int offset, regsize, regn;
const struct bt_definition *scope
= bt_ctf_get_top_level_scope (event,
BT_EVENT_FIELDS);
const struct bt_definition *array
= bt_ctf_get_field (event, scope, "contents");
+ gdb_byte *regs = (gdb_byte *) bt_ctf_get_char_array (array);
- regs = (gdb_byte *) bt_ctf_get_char_array (array);
/* Assume the block is laid out in GDB register number order,
each register with the size that it has in GDB. */
offset = 0;
}
offset += regsize;
}
- return;
- }
-
- regs = alloca (trace_regblock_size);
-
- /* 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);
- if (pc_regno >= 0 && (regno == -1 || regno == pc_regno))
- {
- struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
-
- if (tp != NULL && tp->base.loc)
- {
- /* But don't try to guess if tracepoint is multi-location... */
- if (tp->base.loc->next != NULL)
- {
- 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);
}
/* This is the implementation of target_ops method to_xfer_partial.
struct bt_iter_pos *pos;
int i = 0;
enum target_xfer_status res;
+ /* Records the lowest available address of all blocks that
+ intersects the requested range. */
+ ULONGEST low_addr_available = 0;
gdb_assert (ctf_iter != NULL);
/* Save the current position. */
}
}
+ if (offset < maddr && maddr < (offset + len))
+ if (low_addr_available == 0 || low_addr_available > maddr)
+ low_addr_available = maddr;
+
if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0)
break;
}
/* Requested memory is unavailable in the context of traceframes,
and this address falls within a read-only section, fallback
- to reading from executable. */
+ 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)