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) <data>: New.
	* common/btrace-common.h (btrace_data_clear)
	(btrace_data_append): New.
	* common/btrace-common.c (btrace_data_clear)
	(btrace_data_append): New.
This commit is contained in:
Markus Metzger
2014-02-03 11:40:50 +01:00
parent 010a18a1b1
commit 9be54cae43
5 changed files with 114 additions and 0 deletions

View File

@ -1,3 +1,13 @@
2015-07-02 Markus Metzger <markus.t.metzger@intel.com>
* btrace.c (btrace_fetch): Append the new trace data.
(btrace_clear): Clear the stored trace data.
* btrace.h (btrace_thread_info) <data>: 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 <markus.t.metzger@intel.com> 2015-07-02 Markus Metzger <markus.t.metzger@intel.com>
* nat/linux-btrace.c (linux_enable_bts): Check for * nat/linux-btrace.c (linux_enable_bts): Check for

View File

@ -1260,6 +1260,10 @@ btrace_fetch (struct thread_info *tp)
/* Compute the trace, provided we have any. */ /* Compute the trace, provided we have any. */
if (!btrace_data_empty (&btrace)) 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_clear_history (btinfo);
btrace_compute_ftrace (tp, &btrace); btrace_compute_ftrace (tp, &btrace);
} }
@ -1296,6 +1300,7 @@ btrace_clear (struct thread_info *tp)
btinfo->end = NULL; btinfo->end = NULL;
btinfo->ngaps = 0; btinfo->ngaps = 0;
btrace_data_clear (&btinfo->data);
btrace_clear_history (btinfo); btrace_clear_history (btinfo);
} }

View File

@ -248,6 +248,9 @@ struct btrace_thread_info
the underlying architecture. */ the underlying architecture. */
struct btrace_target_info *target; 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 current branch trace for this thread (both inclusive).
The last instruction of END is the current instruction, which is not The last instruction of END is the current instruction, which is not

View File

@ -91,3 +91,90 @@ btrace_data_empty (struct btrace_data *data)
internal_error (__FILE__, __LINE__, _("Unkown branch trace format.")); 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."));
}

View File

@ -214,7 +214,16 @@ extern void btrace_data_init (struct btrace_data *data);
/* Cleanup DATA. */ /* Cleanup DATA. */
extern void btrace_data_fini (struct btrace_data *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. */ /* Return non-zero if DATA is empty; zero otherwise. */
extern int btrace_data_empty (struct btrace_data *data); 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 */ #endif /* BTRACE_COMMON_H */