static struct traceframe_info * ctf_traceframe_info (struct target_ops *self) { struct traceframe_info *info = XCNEW (struct traceframe_info); const char *name; struct bt_iter_pos *pos; 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); do { struct bt_ctf_event *event = bt_ctf_iter_read_event (ctf_iter); name = bt_ctf_event_name (event); if (name == NULL || strcmp (name, "register") == 0 || strcmp (name, "frame") == 0) ; else if (strcmp (name, "memory") == 0) { const struct bt_definition *scope = bt_ctf_get_top_level_scope (event, BT_EVENT_FIELDS); const struct bt_definition *def; struct mem_range *r; r = VEC_safe_push (mem_range_s, info->memory, NULL); def = bt_ctf_get_field (event, scope, "address"); r->start = bt_ctf_get_uint64 (def); def = bt_ctf_get_field (event, scope, "length"); r->length = (uint16_t) bt_ctf_get_uint64 (def); } else if (strcmp (name, "tsv") == 0) { int vnum; const struct bt_definition *scope = bt_ctf_get_top_level_scope (event, BT_EVENT_FIELDS); const struct bt_definition *def; def = bt_ctf_get_field (event, scope, "num"); vnum = (int) bt_ctf_get_int64 (def); VEC_safe_push (int, info->tvars, vnum); } else { warning (_("Unhandled trace block type (%s) " "while building trace frame info."), name); } if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) break; }
static void ctf_read_tp (struct uploaded_tp **uploaded_tps) { gdb_assert (ctf_iter != NULL); while (1) { struct bt_ctf_event *event; const struct bt_definition *scope; uint32_t u32; int32_t int32; uint64_t u64; struct uploaded_tp *utp = NULL; event = bt_ctf_iter_read_event (ctf_iter); scope = bt_ctf_get_top_level_scope (event, BT_STREAM_EVENT_HEADER); u32 = bt_ctf_get_uint64 (bt_ctf_get_field (event, scope, "id")); if (u32 != CTF_EVENT_ID_TP_DEF) break; scope = bt_ctf_get_top_level_scope (event, BT_EVENT_FIELDS); int32 = (int32_t) bt_ctf_get_int64 (bt_ctf_get_field (event, scope, "number")); u64 = bt_ctf_get_uint64 (bt_ctf_get_field (event, scope, "addr")); utp = get_uploaded_tp (int32, u64, uploaded_tps); SET_INT32_FIELD (event, scope, utp, enabled); SET_INT32_FIELD (event, scope, utp, step); SET_INT32_FIELD (event, scope, utp, pass); SET_INT32_FIELD (event, scope, utp, hit_count); SET_INT32_FIELD (event, scope, utp, type); /* Read 'cmd_strings'. */ SET_ARRAY_FIELD (event, scope, utp, cmd_num, cmd_strings); /* Read 'actions'. */ SET_ARRAY_FIELD (event, scope, utp, action_num, actions); /* Read 'step_actions'. */ SET_ARRAY_FIELD (event, scope, utp, step_action_num, step_actions); SET_STRING_FIELD(event, scope, utp, at_string); SET_STRING_FIELD(event, scope, utp, cond_string); if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) break; } }
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 int ctf_get_tpnum_from_frame_event (struct bt_ctf_event *event) { /* The packet context of events has a field "tpnum". */ const struct bt_definition *scope = bt_ctf_get_top_level_scope (event, BT_STREAM_PACKET_CONTEXT); uint64_t tpnum = bt_ctf_get_uint64 (bt_ctf_get_field (event, scope, "tpnum")); return (int) tpnum; }
static void ctf_read_tsv (struct uploaded_tsv **uploaded_tsvs) { gdb_assert (ctf_iter != NULL); while (1) { struct bt_ctf_event *event; const struct bt_definition *scope; const struct bt_definition *def; uint32_t event_id; struct uploaded_tsv *utsv = NULL; event = bt_ctf_iter_read_event (ctf_iter); scope = bt_ctf_get_top_level_scope (event, BT_STREAM_EVENT_HEADER); event_id = bt_ctf_get_uint64 (bt_ctf_get_field (event, scope, "id")); if (event_id != CTF_EVENT_ID_TSV_DEF) break; scope = bt_ctf_get_top_level_scope (event, BT_EVENT_FIELDS); def = bt_ctf_get_field (event, scope, "number"); utsv = get_uploaded_tsv ((int32_t) bt_ctf_get_int64 (def), uploaded_tsvs); def = bt_ctf_get_field (event, scope, "builtin"); utsv->builtin = (int32_t) bt_ctf_get_int64 (def); def = bt_ctf_get_field (event, scope, "initial_value"); utsv->initial_value = bt_ctf_get_int64 (def); def = bt_ctf_get_field (event, scope, "name"); utsv->name = xstrdup (bt_ctf_get_string (def)); if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) break; } }
uint64_t get_cpu_id(const struct bt_ctf_event *event) { const struct definition *scope; uint64_t cpu_id; scope = bt_ctf_get_top_level_scope(event, BT_STREAM_PACKET_CONTEXT); cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(event, scope, "cpu_id")); if (bt_ctf_field_get_error()) { fprintf(stderr, "[error] get cpu_id\n"); return -1ULL; } return cpu_id; }
char *get_context_comm(const struct bt_ctf_event *event) { const struct definition *scope; char *comm; scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT); comm = bt_ctf_get_char_array(bt_ctf_get_field(event, scope, "_procname")); if (bt_ctf_field_get_error()) { fprintf(stderr, "Missing comm context info\n"); return NULL; } return comm; }
uint64_t get_context_ppid(const struct bt_ctf_event *event) { const struct definition *scope; uint64_t ppid; scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT); ppid = bt_ctf_get_int64(bt_ctf_get_field(event, scope, "_ppid")); if (bt_ctf_field_get_error()) { fprintf(stderr, "Missing ppid context info\n"); return -1ULL; } return ppid; }
guint lttv_traceset_get_cpuid_from_event(LttvEvent *event) { unsigned long timestamp; unsigned int cpu_id; struct bt_ctf_event *ctf_event = event->bt_event; timestamp = bt_ctf_get_timestamp(ctf_event); if (timestamp == -1ULL) { return 0; } const struct bt_definition *scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); if (bt_ctf_field_get_error()) { return 0; } cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(ctf_event, scope, "cpu_id")); if (bt_ctf_field_get_error()) { return 0; } else { return cpu_id; } }
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); }
static void ctf_open (const char *dirname, int from_tty) { struct bt_ctf_event *event; uint32_t event_id; const struct bt_definition *scope; struct uploaded_tsv *uploaded_tsvs = NULL; struct uploaded_tp *uploaded_tps = NULL; if (!dirname) error (_("No CTF directory specified.")); ctf_open_dir (dirname); target_preopen (from_tty); /* Skip the first packet which about the trace status. The first event is "frame". */ event = bt_ctf_iter_read_event (ctf_iter); scope = bt_ctf_get_top_level_scope (event, BT_STREAM_EVENT_HEADER); event_id = bt_ctf_get_uint64 (bt_ctf_get_field (event, scope, "id")); if (event_id != CTF_EVENT_ID_FRAME) error (_("Wrong event id of the first event")); /* The second event is "status". */ bt_iter_next (bt_ctf_get_iter (ctf_iter)); event = bt_ctf_iter_read_event (ctf_iter); scope = bt_ctf_get_top_level_scope (event, BT_STREAM_EVENT_HEADER); event_id = bt_ctf_get_uint64 (bt_ctf_get_field (event, scope, "id")); if (event_id != CTF_EVENT_ID_STATUS) error (_("Wrong event id of the second event")); ctf_read_status (event, current_trace_status ()); ctf_read_tsv (&uploaded_tsvs); ctf_read_tp (&uploaded_tps); event = bt_ctf_iter_read_event (ctf_iter); /* EVENT can be NULL if we've already gone to the end of stream of events. */ if (event != NULL) { scope = bt_ctf_get_top_level_scope (event, BT_STREAM_EVENT_HEADER); event_id = bt_ctf_get_uint64 (bt_ctf_get_field (event, scope, "id")); if (event_id != CTF_EVENT_ID_FRAME) error (_("Wrong event id of the first event of the second packet")); } start_pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); gdb_assert (start_pos->type == BT_SEEK_RESTORE); trace_dirname = xstrdup (dirname); push_target (&ctf_ops); inferior_appeared (current_inferior (), CTF_PID); inferior_ptid = pid_to_ptid (CTF_PID); add_thread_silent (inferior_ptid); merge_uploaded_trace_state_variables (&uploaded_tsvs); merge_uploaded_tracepoints (&uploaded_tps); post_create_inferior (&ctf_ops, from_tty); }
int getProcessInfosFromEvent(LttvEvent *event, GString* processInfos) { int pid=0, tid=0, ppid=0; const char *procname; unsigned long timestamp; int ret = 0; gboolean noError = TRUE; guint cpu; LttvTraceState *state = event->state; LttvProcessState *process; struct bt_ctf_event *ctf_event = event->bt_event; cpu = lttv_traceset_get_cpuid_from_event(event); process = state->running_process[cpu]; timestamp = bt_ctf_get_timestamp(ctf_event); pid = process->pid; tid = process->tgid; ppid = process->ppid; procname = g_quark_to_string(process->name); if (timestamp == -1ULL) { noError = FALSE; } #if 0 if (noError) { scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_EVENT_CONTEXT); if (bt_ctf_field_get_error()) { noError = FALSE; } } if (noError) { pid = bt_ctf_get_int64(bt_ctf_get_field(ctf_event, scope, "_pid")); if (bt_ctf_field_get_error()) { noError = FALSE; } } if (noError) { tid = bt_ctf_get_int64(bt_ctf_get_field(ctf_event, scope, "_tid")); if (bt_ctf_field_get_error()) { noError = FALSE; } } if (noError) { ppid = bt_ctf_get_int64(bt_ctf_get_field(ctf_event, scope, "_ppid")); if (bt_ctf_field_get_error()) { noError = FALSE; } } if (noError) { procname = bt_ctf_get_char_array(bt_ctf_get_field(ctf_event, scope, "_procname")); if (bt_ctf_field_get_error()) { noError = FALSE; } } #endif if (noError||1) { g_string_append_printf(processInfos, "%u, %u, %s, %u. %s, %s", pid, tid, procname, ppid, g_quark_to_string(process->state->t), g_quark_to_string(process->state->s)); } else { ret = -1; } return ret; }
/* * hook on each event to check the timestamp and refresh the display if * necessary */ enum bt_cb_ret textdump(struct bt_ctf_event *call_data, void *private_data) { unsigned long timestamp; uint64_t delta; struct tm start; uint64_t ts_nsec_start; int pid, cpu_id, tid, ret, lookup, current_syscall = 0; const struct bt_definition *scope; const char *hostname, *procname; struct cputime *cpu; char *from_syscall = NULL; int syscall_exit = 0; timestamp = bt_ctf_get_timestamp(call_data); /* can happen in network live when tracing is idle */ if (timestamp < last_event_ts) goto end_stop; last_event_ts = timestamp; start = format_timestamp(timestamp); ts_nsec_start = timestamp % NSEC_PER_SEC; pid = get_context_pid(call_data); if (pid == -1ULL && opt_tid) { goto error; } tid = get_context_tid(call_data); hostname = get_context_hostname(call_data); if (opt_child) lookup = pid; else lookup = tid; if (opt_tid || opt_procname || opt_exec_name) { if (!lookup_filter_tid_list(lookup)) { /* To display when a process of ours in getting scheduled in */ if (strcmp(bt_ctf_event_name(call_data), "sched_switch") == 0) { int next_tid; scope = bt_ctf_get_top_level_scope(call_data, BT_EVENT_FIELDS); next_tid = bt_ctf_get_int64(bt_ctf_get_field(call_data, scope, "_next_tid")); if (bt_ctf_field_get_error()) { fprintf(stderr, "Missing next_tid field\n"); goto error; } if (!lookup_filter_tid_list(next_tid)) { if (!opt_all) goto end; } else { if (opt_all) fprintf(output, "%c[1m", 27); } } else if (!opt_all) { goto end; } } else { if (opt_all) fprintf(output, "%c[1m", 27); } } if (((strncmp(bt_ctf_event_name(call_data), "exit_syscall", 12)) == 0) || ((strncmp(bt_ctf_event_name(call_data), "syscall_exit", 12)) == 0)) { syscall_exit = 1; } if (last_syscall && !syscall_exit) { last_syscall = NULL; fprintf(output, " ...interrupted...\n"); } cpu_id = get_cpu_id(call_data); procname = get_context_comm(call_data); if ((strncmp(bt_ctf_event_name(call_data), "sys_", 4) == 0) || (strncmp(bt_ctf_event_name(call_data), "syscall_entry", 13) == 0)){ cpu = get_cpu(cpu_id); cpu->current_syscall = g_new0(struct syscall, 1); cpu->current_syscall->name = strdup(bt_ctf_event_name(call_data)); cpu->current_syscall->ts_start = timestamp; cpu->current_syscall->cpu_id = cpu_id; last_syscall = cpu->current_syscall; current_syscall = 1; } else if (syscall_exit) {