From 9be54cae43929ab989fcd44dfcf8d3313a55f7a0 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Mon, 3 Feb 2014 11:40:50 +0100 Subject: [PATCH] btrace: store raw btrace data Store the raw branch trace data that has been read from the target. This data can be used for maintenance commands as well as for generating a core file for the "record save" command. gdb/ * 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. --- gdb/ChangeLog | 10 ++++++ gdb/btrace.c | 5 +++ gdb/btrace.h | 3 ++ gdb/common/btrace-common.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ gdb/common/btrace-common.h | 9 +++++ 5 files changed, 114 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a4cce4d..807d19f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,15 @@ 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 PERF_ATTR_SIZE_VER5. Check for data_offset and data_size fields. Use them. diff --git a/gdb/btrace.c b/gdb/btrace.c index 561ee7c..87b2601 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 c25dc84..0845b78 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 676428e..95193eb 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 ebae17e..f22efc5 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 */ -- 2.7.4