+#if !defined(HAVE_LIBEXPAT)
+
+struct traceframe_info *
+parse_traceframe_info (const char *tframe_info)
+{
+ static int have_warned;
+
+ if (!have_warned)
+ {
+ have_warned = 1;
+ warning (_("Can not parse XML trace frame info; XML support "
+ "was disabled at compile time"));
+ }
+
+ return NULL;
+}
+
+#else /* HAVE_LIBEXPAT */
+
+#include "xml-support.h"
+
+/* Handle the start of a <memory> element. */
+
+static void
+traceframe_info_start_memory (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ struct traceframe_info *info = user_data;
+ struct mem_range *r = VEC_safe_push (mem_range_s, info->memory, NULL);
+ ULONGEST *start_p, *length_p;
+
+ start_p = xml_find_attribute (attributes, "start")->value;
+ length_p = xml_find_attribute (attributes, "length")->value;
+
+ r->start = *start_p;
+ r->length = *length_p;
+}
+
+/* Discard the constructed trace frame info (if an error occurs). */
+
+static void
+free_result (void *p)
+{
+ struct traceframe_info *result = p;
+
+ free_traceframe_info (result);
+}
+
+/* The allowed elements and attributes for an XML memory map. */
+
+static const struct gdb_xml_attribute memory_attributes[] = {
+ { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "length", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element traceframe_info_children[] = {
+ { "memory", memory_attributes, NULL,
+ GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+ traceframe_info_start_memory, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element traceframe_info_elements[] = {
+ { "traceframe-info", NULL, traceframe_info_children, GDB_XML_EF_NONE,
+ NULL, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* Parse a traceframe-info XML document. */
+
+struct traceframe_info *
+parse_traceframe_info (const char *tframe_info)
+{
+ struct traceframe_info *result;
+ struct cleanup *back_to;
+
+ result = XCNEW (struct traceframe_info);
+ back_to = make_cleanup (free_result, result);
+
+ if (gdb_xml_parse_quick (_("trace frame info"),
+ "traceframe-info.dtd", traceframe_info_elements,
+ tframe_info, result) == 0)
+ {
+ /* Parsed successfully, keep the result. */
+ discard_cleanups (back_to);
+
+ return result;
+ }
+
+ do_cleanups (back_to);
+ return NULL;
+}
+
+#endif /* HAVE_LIBEXPAT */
+
+/* Returns the traceframe_info object for the current traceframe.
+ This is where we avoid re-fetching the object from the target if we
+ already have it cached. */
+
+static struct traceframe_info *
+get_traceframe_info (void)
+{
+ if (traceframe_info == NULL)
+ traceframe_info = target_traceframe_info ();
+
+ return traceframe_info;
+}
+
+/* If the target supports the query, return in RESULT the set of
+ collected memory in the current traceframe, found within the LEN
+ bytes range starting at MEMADDR. Returns true if the target
+ supports the query, otherwise returns false, and RESULT is left
+ undefined. */
+
+int
+traceframe_available_memory (VEC(mem_range_s) **result,
+ CORE_ADDR memaddr, ULONGEST len)
+{
+ struct traceframe_info *info = get_traceframe_info ();
+
+ if (info != NULL)
+ {
+ struct mem_range *r;
+ int i;
+
+ *result = NULL;
+
+ for (i = 0; VEC_iterate (mem_range_s, info->memory, i, r); i++)
+ if (mem_ranges_overlap (r->start, r->length, memaddr, len))
+ {
+ ULONGEST lo1, hi1, lo2, hi2;
+ struct mem_range *nr;
+
+ lo1 = memaddr;
+ hi1 = memaddr + len;
+
+ lo2 = r->start;
+ hi2 = r->start + r->length;
+
+ nr = VEC_safe_push (mem_range_s, *result, NULL);
+
+ nr->start = max (lo1, lo2);
+ nr->length = min (hi1, hi2) - nr->start;
+ }
+
+ normalize_mem_ranges (*result);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Implementation of `sdata' variable. */
+
+static const struct internalvar_funcs sdata_funcs =
+{
+ sdata_make_value,
+ NULL,
+ NULL
+};
+