diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a4cce4d43e..807d19ffa0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2015-07-02 Markus Metzger + + * btrace.c (btrace_fetch): Append the new trace data. + (btrace_clear): Clear the stored trace data. + * btrace.h (btrace_thread_info) : New. + * common/btrace-common.h (btrace_data_clear) + (btrace_data_append): New. + * common/btrace-common.c (btrace_data_clear) + (btrace_data_append): New. + 2015-07-02 Markus Metzger * nat/linux-btrace.c (linux_enable_bts): Check for diff --git a/gdb/btrace.c b/gdb/btrace.c index 561ee7cb76..87b260109a 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -1260,6 +1260,10 @@ btrace_fetch (struct thread_info *tp) /* Compute the trace, provided we have any. */ if (!btrace_data_empty (&btrace)) { + /* Store the raw trace data. The stored data will be cleared in + btrace_clear, so we always append the new trace. */ + btrace_data_append (&btinfo->data, &btrace); + btrace_clear_history (btinfo); btrace_compute_ftrace (tp, &btrace); } @@ -1296,6 +1300,7 @@ btrace_clear (struct thread_info *tp) btinfo->end = NULL; btinfo->ngaps = 0; + btrace_data_clear (&btinfo->data); btrace_clear_history (btinfo); } diff --git a/gdb/btrace.h b/gdb/btrace.h index c25dc846e2..0845b78d0c 100644 --- a/gdb/btrace.h +++ b/gdb/btrace.h @@ -248,6 +248,9 @@ struct btrace_thread_info the underlying architecture. */ struct btrace_target_info *target; + /* The raw branch trace data for the below branch trace. */ + struct btrace_data data; + /* The current branch trace for this thread (both inclusive). The last instruction of END is the current instruction, which is not diff --git a/gdb/common/btrace-common.c b/gdb/common/btrace-common.c index 676428e155..95193ebc08 100644 --- a/gdb/common/btrace-common.c +++ b/gdb/common/btrace-common.c @@ -91,3 +91,90 @@ btrace_data_empty (struct btrace_data *data) internal_error (__FILE__, __LINE__, _("Unkown branch trace format.")); } + +/* See btrace-common.h. */ + +void +btrace_data_clear (struct btrace_data *data) +{ + btrace_data_fini (data); + btrace_data_init (data); +} + +/* See btrace-common.h. */ + +int +btrace_data_append (struct btrace_data *dst, + const struct btrace_data *src) +{ + switch (src->format) + { + case BTRACE_FORMAT_NONE: + return 0; + + case BTRACE_FORMAT_BTS: + switch (dst->format) + { + default: + return -1; + + case BTRACE_FORMAT_NONE: + dst->format = BTRACE_FORMAT_BTS; + dst->variant.bts.blocks = NULL; + + /* Fall-through. */ + case BTRACE_FORMAT_BTS: + { + unsigned int blk; + + /* We copy blocks in reverse order to have the oldest block at + index zero. */ + blk = VEC_length (btrace_block_s, src->variant.bts.blocks); + while (blk != 0) + { + btrace_block_s *block; + + block = VEC_index (btrace_block_s, src->variant.bts.blocks, + --blk); + + VEC_safe_push (btrace_block_s, dst->variant.bts.blocks, block); + } + } + } + return 0; + + case BTRACE_FORMAT_PT: + switch (dst->format) + { + default: + return -1; + + case BTRACE_FORMAT_NONE: + dst->format = BTRACE_FORMAT_PT; + dst->variant.pt.data = NULL; + dst->variant.pt.size = 0; + + /* fall-through. */ + case BTRACE_FORMAT_BTS: + { + gdb_byte *data; + unsigned long size; + + size = src->variant.pt.size + dst->variant.pt.size; + data = xmalloc (size); + + memcpy (data, dst->variant.pt.data, dst->variant.pt.size); + memcpy (data + dst->variant.pt.size, src->variant.pt.data, + src->variant.pt.size); + + xfree (dst->variant.pt.data); + + dst->variant.pt.data = data; + dst->variant.pt.size = size; + } + } + return 0; + } + + internal_error (__FILE__, __LINE__, _("Unkown branch trace format.")); +} diff --git a/gdb/common/btrace-common.h b/gdb/common/btrace-common.h index ebae17eee4..f22efc5a81 100644 --- a/gdb/common/btrace-common.h +++ b/gdb/common/btrace-common.h @@ -214,7 +214,16 @@ extern void btrace_data_init (struct btrace_data *data); /* Cleanup DATA. */ extern void btrace_data_fini (struct btrace_data *data); +/* Clear DATA. */ +extern void btrace_data_clear (struct btrace_data *data); + /* Return non-zero if DATA is empty; zero otherwise. */ extern int btrace_data_empty (struct btrace_data *data); +/* Append the branch trace data from SRC to the end of DST. + Both SRC and DST must use the same format. + Returns zero on success; a negative number otherwise. */ +extern int btrace_data_append (struct btrace_data *dst, + const struct btrace_data *src); + #endif /* BTRACE_COMMON_H */