int bt_iter_init(struct bt_iter *iter, struct bt_context *ctx, const struct bt_iter_pos *begin_pos, const struct bt_iter_pos *end_pos) { int i; int ret = 0; if (!iter || !ctx || !ctx->tc || !ctx->tc->array) return -EINVAL; if (ctx->current_iterator) { ret = -1; goto error_ctx; } iter->stream_heap = g_new(struct ptr_heap, 1); iter->end_pos = end_pos; bt_context_get(ctx); iter->ctx = ctx; ret = bt_heap_init(iter->stream_heap, 0, stream_compare); if (ret < 0) goto error_heap_init; for (i = 0; i < ctx->tc->array->len; i++) { struct bt_trace_descriptor *td_read; td_read = g_ptr_array_index(ctx->tc->array, i); if (!td_read) continue; ret = bt_iter_add_trace(iter, td_read); if (ret < 0) goto error; } ctx->current_iterator = iter; if (begin_pos && begin_pos->type != BT_SEEK_BEGIN) { ret = bt_iter_set_pos(iter, begin_pos); if (ret) { goto error; } } return ret; error: bt_heap_free(iter->stream_heap); error_heap_init: g_free(iter->stream_heap); iter->stream_heap = NULL; error_ctx: return ret; }
static int ctf_get_trace_state_variable_value (struct target_ops *self, int tsvnum, LONGEST *val) { struct bt_iter_pos *pos; int found = 0; gdb_assert (ctf_iter != NULL); /* Save the current position. */ pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); gdb_assert (pos->type == BT_SEEK_RESTORE); /* Iterate through the traceframe's blocks, looking for 'V' block. */ while (1) { struct bt_ctf_event *event = bt_ctf_iter_read_event (ctf_iter); const char *name = bt_ctf_event_name (event); if (name == NULL || strcmp (name, "frame") == 0) break; else if (strcmp (name, "tsv") == 0) { const struct bt_definition *scope; const struct bt_definition *def; scope = bt_ctf_get_top_level_scope (event, BT_EVENT_FIELDS); def = bt_ctf_get_field (event, scope, "num"); if (tsvnum == (int32_t) bt_ctf_get_uint64 (def)) { def = bt_ctf_get_field (event, scope, "val"); *val = bt_ctf_get_uint64 (def); found = 1; } } if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) break; } /* Restore the position. */ bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); return found; }
static CORE_ADDR ctf_get_traceframe_address (void) { struct bt_ctf_event *event = NULL; struct bt_iter_pos *pos; CORE_ADDR addr = 0; gdb_assert (ctf_iter != NULL); pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); gdb_assert (pos->type == BT_SEEK_RESTORE); while (1) { const char *name; struct bt_ctf_event *event1; event1 = bt_ctf_iter_read_event (ctf_iter); name = bt_ctf_event_name (event1); if (name == NULL) break; else if (strcmp (name, "frame") == 0) { event = event1; break; } if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) break; } if (event != NULL) { int tpnum = ctf_get_tpnum_from_frame_event (event); struct tracepoint *tp = get_tracepoint_by_number_on_target (tpnum); if (tp && tp->base.loc) addr = tp->base.loc->address; } /* Restore the position. */ bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); return addr; }
static int ctf_trace_find (struct target_ops *self, enum trace_find_type type, int num, CORE_ADDR addr1, CORE_ADDR addr2, int *tpp) { int ret = -1; int tfnum = 0; int found = 0; struct bt_iter_pos pos; if (num == -1) { if (tpp != NULL) *tpp = -1; return -1; } gdb_assert (ctf_iter != NULL); /* Set iterator back to the start. */ bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), start_pos); while (1) { int id; struct bt_ctf_event *event; const char *name; event = bt_ctf_iter_read_event (ctf_iter); name = bt_ctf_event_name (event); if (event == NULL || name == NULL) break; if (strcmp (name, "frame") == 0) { CORE_ADDR tfaddr; if (type == tfind_number) { /* Looking for a specific trace frame. */ if (tfnum == num) found = 1; } else { /* Start from the _next_ trace frame. */ if (tfnum > get_traceframe_number ()) { switch (type) { case tfind_tp: { struct tracepoint *tp = get_tracepoint (num); if (tp != NULL && (tp->number_on_target == ctf_get_tpnum_from_frame_event (event))) found = 1; break; } case tfind_pc: tfaddr = ctf_get_traceframe_address (); if (tfaddr == addr1) found = 1; break; case tfind_range: tfaddr = ctf_get_traceframe_address (); if (addr1 <= tfaddr && tfaddr <= addr2) found = 1; break; case tfind_outside: tfaddr = ctf_get_traceframe_address (); if (!(addr1 <= tfaddr && tfaddr <= addr2)) found = 1; break; default: internal_error (__FILE__, __LINE__, _("unknown tfind type")); } } } if (found) { if (tpp != NULL) *tpp = ctf_get_tpnum_from_frame_event (event); /* Skip the event "frame". */ bt_iter_next (bt_ctf_get_iter (ctf_iter)); return tfnum; } tfnum++; } if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) break; } return -1; }
static enum target_xfer_status ctf_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. */ if (object != TARGET_OBJECT_MEMORY) return -1; if (readbuf == NULL) error (_("ctf_xfer_partial: trace file is read-only")); if (get_traceframe_number () != -1) { 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. */ pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); gdb_assert (pos->type == BT_SEEK_RESTORE); /* Iterate through the traceframe's blocks, looking for memory. */ while (1) { ULONGEST amt; uint64_t maddr; uint16_t mlen; enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); const struct bt_definition *scope; const struct bt_definition *def; struct bt_ctf_event *event = bt_ctf_iter_read_event (ctf_iter); const char *name = bt_ctf_event_name (event); if (name == NULL || strcmp (name, "frame") == 0) break; else if (strcmp (name, "memory") != 0) { if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) break; continue; } scope = bt_ctf_get_top_level_scope (event, BT_EVENT_FIELDS); def = bt_ctf_get_field (event, scope, "address"); maddr = bt_ctf_get_uint64 (def); def = bt_ctf_get_field (event, scope, "length"); mlen = (uint16_t) bt_ctf_get_uint64 (def); /* 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)) { const struct bt_definition *array = bt_ctf_get_field (event, scope, "contents"); const struct bt_declaration *decl = bt_ctf_get_decl_from_def (array); gdb_byte *contents; int k; contents = xmalloc (mlen); for (k = 0; k < mlen; k++) { const struct bt_definition *element = bt_ctf_get_index (event, array, k); contents[k] = (gdb_byte) bt_ctf_get_uint64 (element); } amt = (maddr + mlen) - offset; if (amt > len) amt = len; memcpy (readbuf, &contents[offset - maddr], amt); xfree (contents); /* Restore the position. */ bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); if (amt == 0) return TARGET_XFER_EOF; else { *xfered_len = amt; return TARGET_XFER_OK; } } 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; } /* Restore the position. */ bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); /* 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 { /* Fallback to reading from read-only sections. */ return section_table_read_available_memory (readbuf, offset, len, xfered_len); } }
static void ctf_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regno) { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct bt_ctf_event *event = NULL; struct bt_iter_pos *pos; /* An uninitialized reg size says we're not going to be successful at getting register blocks. */ if (trace_regblock_size == 0) return; gdb_assert (ctf_iter != NULL); /* Save the current position. */ pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); gdb_assert (pos->type == BT_SEEK_RESTORE); while (1) { const char *name; struct bt_ctf_event *event1; event1 = bt_ctf_iter_read_event (ctf_iter); name = bt_ctf_event_name (event1); if (name == NULL || strcmp (name, "frame") == 0) break; else if (strcmp (name, "register") == 0) { event = event1; break; } if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) break; } /* Restore the position. */ bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), 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); /* 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) { if (regno == regn) { regcache_raw_supply (regcache, regno, regs + offset); break; } else if (regno == -1) { regcache_raw_supply (regcache, regn, regs + offset); } } offset += regsize; } } else tracefile_fetch_registers (regcache, regno); }
void lttv_traceset_seek_to_position(const LttvTracesetPosition *traceset_pos) { bt_iter_set_pos(bt_ctf_get_iter(traceset_pos->iter), traceset_pos->bt_pos); }