The XML file contains a control flow graph, where each edge is annotated with a context-dependent value. The parser reads this information into a data structure within CPUState.
Signed-off-by: Peer Adelt <peer.ad...@c-lab.de> --- include/qom/cpu.h | 9 ++ include/tb-annotation/tb-annotation-parser.h | 29 +++++ include/tb-annotation/tb-annotation.h | 64 ++++++++++ tb-annotation/tb-annotation-parser.c | 174 +++++++++++++++++++++++++++ 4 files changed, 276 insertions(+) create mode 100644 include/tb-annotation/tb-annotation-parser.h create mode 100644 include/tb-annotation/tb-annotation.h create mode 100644 tb-annotation/tb-annotation-parser.c diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 51a1323..afc532b 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -30,6 +30,10 @@ #include "qemu/thread.h" #include "qemu/typedefs.h" +#ifdef CONFIG_TB_ANNOTATION +#include "tb-annotation/tb-annotation.h" +#endif + typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size, void *opaque); @@ -329,6 +333,11 @@ struct CPUState { */ bool throttle_thread_scheduled; +#ifdef CONFIG_TB_ANNOTATION + /* Used to annotate cpu state during tb execution */ + TbAnnotation *tb_annotation; +#endif + /* Note that this is accessed at the start of every TB via a negative offset from AREG0. Leave this field at the end so as to make the (absolute value) offset as small as possible. This reduces code diff --git a/include/tb-annotation/tb-annotation-parser.h b/include/tb-annotation/tb-annotation-parser.h new file mode 100644 index 0000000..aacab8e --- /dev/null +++ b/include/tb-annotation/tb-annotation-parser.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015-2016 Bastian Koppelmann + * Peer Adelt + * C-Lab/Paderborn University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INCLUDE_TB_ANNOTATION_PARSER_H_ +#define INCLUDE_TB_ANNOTATION_PARSER_H_ + +#include "tb-annotation/tb-annotation.h" + +void tb_annotation_xml_init(const char *filename); +void tb_annotation_xml_close(void); +TbAnnotation *tb_annotation_parse(const char *filename); + +#endif /* INCLUDE_TB_ANNOTATION_PARSER_H_ */ diff --git a/include/tb-annotation/tb-annotation.h b/include/tb-annotation/tb-annotation.h new file mode 100644 index 0000000..e1093b2 --- /dev/null +++ b/include/tb-annotation/tb-annotation.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015-2016 Bastian Koppelmann + * Peer Adelt + * C-Lab/Paderborn University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INCLUDE_TB_ANNOTATION_H_ +#define INCLUDE_TB_ANNOTATION_H_ + +#include <glib.h> + +typedef struct tb_leaving_edge_tuple TbAnnotationLeavingEdgeTuple; +typedef struct tb_annotation_block TbAnnotationBlock; +typedef struct tb_annotation_edge TbAnnotationEdge; +typedef struct tb_annotation TbAnnotation; + +struct tb_leaving_edge_tuple { + TbAnnotationEdge *out1; + TbAnnotationEdge *out2; +}; + +struct tb_annotation_block { + uint8_t is_end_block; + const char *id; + unsigned int address; + /* This hashtable points to all pairs of leaving edges + * from all source contexts. + * Note: string -> tb_leaving_edge_tuple + */ + GHashTable *out_edges_hash_table; +}; + +struct tb_annotation_edge { + TbAnnotationBlock *source; + TbAnnotationBlock *target; + const char *source_context; + const char *target_context; + unsigned int value; +}; + +struct tb_annotation { + + TbAnnotationBlock *last_block; + const char *last_ctx; + /* Hashes from PC to TbAnnotationBlock */ + GHashTable *tb_annotation_blocks; + unsigned int value_sum; + +}; + +#endif /* INCLUDE_TB_ANNOTATION_H_ */ diff --git a/tb-annotation/tb-annotation-parser.c b/tb-annotation/tb-annotation-parser.c new file mode 100644 index 0000000..b3cb2e7 --- /dev/null +++ b/tb-annotation/tb-annotation-parser.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015-2016 Bastian Koppelmann + * Peer Adelt + * C-Lab/Paderborn University + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <libxml/parser.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> +#include <libxml/tree.h> + +#include "tb-annotation/tb-annotation.h" +#include "tb-annotation/tb-annotation-parser.h" + +xmlDocPtr tb_annotation_doc; +xmlXPathContextPtr tb_annotation_xpathctx; +xmlXPathObjectPtr tb_annotation_xpath; + +void tb_annotation_xml_init(const char *filename) +{ + + /* Load XML file */ + tb_annotation_doc = xmlParseFile(filename); + assert(tb_annotation_doc); + + /* Create XPath evaluation context */ + tb_annotation_xpathctx = xmlXPathNewContext(tb_annotation_doc); + assert(tb_annotation_xpathctx); +} + +void tb_annotation_xml_close(void) +{ + + xmlXPathFreeObject(tb_annotation_xpath); + xmlXPathFreeContext(tb_annotation_xpathctx); + xmlFreeDoc(tb_annotation_doc); +} + +static int32_t tb_annotation_xml_evalxpath(const char *xpath, + xmlNodeSetPtr *nodes) +{ + + /* Evaluate the expression */ + tb_annotation_xpath = xmlXPathEvalExpression(BAD_CAST xpath, + tb_annotation_xpathctx); + assert(tb_annotation_xpath); + + /* Set the return value */ + *nodes = tb_annotation_xpath->nodesetval; + return tb_annotation_xpath->nodesetval->nodeNr; +} + +TbAnnotation *tb_annotation_parse(const char *filename) +{ + int32_t i; + xmlNodeSetPtr nodes = NULL; + TbAnnotationBlock *cur_block; + TbAnnotationLeavingEdgeTuple *cur_leaving_edge_tuple; + TbAnnotationEdge *cur_edge; + GHashTable *id_to_block = g_hash_table_new(g_str_hash, g_str_equal); + TbAnnotation *tba = g_new0(TbAnnotation, 1); + tba->tb_annotation_blocks = g_hash_table_new(g_int_hash, g_int_equal); + + /* Open XML file */ + tb_annotation_xml_init(filename); + + /* Parse Blocks */ + tb_annotation_xml_evalxpath("/QEMU-annotation/Blocks/Block", &nodes); + for (i = 0; i < nodes->nodeNr; i++) { + + /* Read XML description of current block */ + const char *id = (const char *) xmlGetNoNsProp( + nodes->nodeTab[i], BAD_CAST "id"); + const char *address_str = (const char *) xmlGetNoNsProp( + nodes->nodeTab[i], BAD_CAST "address"); + + /* Create the block */ + cur_block = g_new0(TbAnnotationBlock, 1); + cur_block->out_edges_hash_table = g_hash_table_new( + g_str_hash, g_str_equal); + cur_block->id = id; + cur_block->address = -1; + + if (g_strcmp0("None", address_str) == 0) { + + cur_block->is_end_block = 1; + + } else { + + cur_block->is_end_block = 0; + sscanf(address_str, "%x", &cur_block->address); + + /* Store current block in TbAnnotations PC -> block map */ + g_hash_table_insert(tba->tb_annotation_blocks, &cur_block->address, + cur_block); + } + + /* Store in id -> block map for edge creation */ + g_hash_table_insert(id_to_block, (gpointer) id, cur_block); + } + + /* Parse Edges (also adding out_edges to blocks) */ + tb_annotation_xml_evalxpath("/QEMU-annotation/Edges/Edge", &nodes); + for (i = 0; i < nodes->nodeNr; i++) { + + /* Read XML description of current edge */ + const char *source_id = (const char *) xmlGetNoNsProp( + nodes->nodeTab[i], BAD_CAST "source"); + const char *source_ctx = (const char *) xmlGetNoNsProp( + nodes->nodeTab[i], BAD_CAST "source_context"); + const char *target_id = (const char *) xmlGetNoNsProp( + nodes->nodeTab[i], BAD_CAST "target"); + const char *target_ctx = (const char *) xmlGetNoNsProp( + nodes->nodeTab[i], BAD_CAST "target_context"); + const char *value_str = (const char *) xmlGetNoNsProp( + nodes->nodeTab[i], BAD_CAST "value"); + + /* Create the edge */ + cur_edge = g_new0(TbAnnotationEdge, 1); + cur_edge->source = g_hash_table_lookup(id_to_block, source_id); + cur_edge->target = g_hash_table_lookup(id_to_block, target_id); + cur_edge->source_context = source_ctx; + cur_edge->target_context = target_ctx; + sscanf(value_str, "%u", &cur_edge->value); + + /* Store this edge in source blocks leaving_edge_tuple */ + cur_leaving_edge_tuple = g_hash_table_lookup( + cur_edge->source->out_edges_hash_table, + cur_edge->source_context); + if (cur_leaving_edge_tuple == NULL) { + cur_leaving_edge_tuple = g_new0(TbAnnotationLeavingEdgeTuple, 1); + g_hash_table_insert(cur_edge->source->out_edges_hash_table, + (gpointer) cur_edge->source_context, + cur_leaving_edge_tuple); + } + /* There must be free space in the leaving_edge_tuple ... */ + assert(cur_leaving_edge_tuple->out1 == NULL || + cur_leaving_edge_tuple->out2 == NULL); + if (cur_leaving_edge_tuple->out1 == NULL) { + cur_leaving_edge_tuple->out1 = cur_edge; + } else { + cur_leaving_edge_tuple->out2 = cur_edge; + } + } + + /* Parse Startcontext */ + tb_annotation_xml_evalxpath("/QEMU-annotation/Start-context", &nodes); + assert(nodes->nodeNr == 1); + tba->last_ctx = (const char *) xmlGetNoNsProp(nodes->nodeTab[0], + BAD_CAST "value"); + + /* Destroy temporary block id -> block map */ + g_hash_table_destroy(id_to_block); + + /* Close XML file */ + tb_annotation_xml_close(); + + /* Return TbAnnotation data */ + return tba; +} -- 2.5.0