1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdlib.h>
17
18 #include "test-malloc-info-stats-print.h"
19 #include "libxml/parser.h"
20
get_text_from_children(xmlNodePtr children)21 static const xmlChar *get_text_from_children(xmlNodePtr children)
22 {
23 for (xmlNodePtr child_node = children; child_node != NULL; child_node = child_node->next) {
24 if (child_node->type == XML_TEXT_NODE) {
25 return child_node->content;
26 }
27 }
28 return NULL;
29 }
30
get_attribute(const char * attr_name,xmlNodePtr node)31 static const xmlChar *get_attribute(const char *attr_name, xmlNodePtr node)
32 {
33 for (xmlAttrPtr curr_attr = node->properties; curr_attr != NULL; curr_attr = curr_attr->next) {
34 if (xmlStrEqual(curr_attr->name, (const xmlChar *) attr_name)) {
35 return get_text_from_children(curr_attr->children);
36 }
37 }
38 return NULL;
39 }
40
find_child_node_with_attr(const char * name,const char * attr_name,const char * attr_value,xmlNodePtr parent)41 static xmlNodePtr find_child_node_with_attr(const char *name, const char *attr_name, const char *attr_value, xmlNodePtr parent)
42 {
43 if (parent == NULL) {
44 return NULL;
45 }
46 for (xmlNodePtr curr_node = parent->children; curr_node != NULL; curr_node = curr_node->next) {
47 if (curr_node->type == XML_ELEMENT_NODE && xmlStrEqual(curr_node->name, (xmlChar *) name)) {
48 if (attr_name == NULL) {
49 return curr_node;
50 }
51 if (xmlStrEqual(get_attribute(attr_name, curr_node), (const xmlChar *) attr_value)) {
52 return curr_node;
53 }
54 }
55 }
56 return NULL;
57 }
58
find_child_node(const char * name,xmlNodePtr parent)59 static xmlNodePtr find_child_node(const char *name, xmlNodePtr parent)
60 {
61 return find_child_node_with_attr(name, NULL, NULL, parent);
62 }
63
get_node_text(xmlNodePtr node_ptr)64 static const char *get_node_text(xmlNodePtr node_ptr)
65 {
66 if (node_ptr == NULL) {
67 return NULL;
68 }
69 return (const char *) get_text_from_children(node_ptr->children);
70 }
71
stderr_stats_cb(void)72 static void stderr_stats_cb(void)
73 {
74 malloc_info(0, stderr);
75 }
76
parse_amount(const char * s)77 static long long parse_amount(const char *s)
78 {
79 if (s == NULL) {
80 return -1;
81 }
82 char *end_ptr;
83 long long result = strtoll(s, &end_ptr, 10);
84 if (end_ptr != s + strlen(s)) {
85 return -1;
86 }
87 if (result < 0) {
88 return -1;
89 }
90 return result;
91 }
92
find_thread_in_document(xmlDocPtr doc_ptr,const char * thread_id)93 static xmlNodePtr find_thread_in_document(xmlDocPtr doc_ptr, const char *thread_id)
94 {
95 xmlNodePtr root_element = xmlDocGetRootElement(doc_ptr);
96 return find_child_node_with_attr("thread", "id", thread_id, find_child_node("threads", root_element));
97 }
98
populate_thread_stats(const char * output,const char * thread_id,malloc_thread_stats_t * stats)99 static int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats)
100 {
101 xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
102 if (doc_ptr == NULL) {
103 return 0;
104 }
105 xmlNodePtr thread_root = find_thread_in_document(doc_ptr, thread_id);
106 long long total_allocated_memory =
107 parse_amount(get_node_text(find_child_node("total_allocated_memory", thread_root)));
108 long long total_mmapped_memory =
109 parse_amount(get_node_text(find_child_node("total_mmapped_memory", thread_root)));
110 long long mmapped_regions =
111 parse_amount(get_node_text(find_child_node("mmapped_regions", thread_root)));
112 xmlFreeDoc(doc_ptr);
113
114 if (total_allocated_memory == -1 || total_mmapped_memory == -1 || mmapped_regions == -1) {
115 return 0;
116 }
117 stats->total_allocated_memory = total_allocated_memory;
118 stats->total_mmapped_memory = total_mmapped_memory;
119 stats->mmapped_regions = mmapped_regions;
120 return 1;
121 }
122
populate_total_free_heap_space(const char * output,long long * total_free_heap_space)123 static int populate_total_free_heap_space(const char *output, long long *total_free_heap_space)
124 {
125 xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
126 if (doc_ptr == NULL) {
127 return 0;
128 }
129 xmlNodePtr heap_space_root = find_child_node("total_free_heap_space", xmlDocGetRootElement(doc_ptr));
130 long long total_free_heap_space_parsed = parse_amount(get_node_text(heap_space_root));
131 xmlFreeDoc(doc_ptr);
132
133 if (total_free_heap_space_parsed == -1) {
134 return 0;
135 }
136 *total_free_heap_space = total_free_heap_space_parsed;
137 return 1;
138 }
139
is_thread_in_output(const char * output,const char * thread_id)140 static int is_thread_in_output(const char *output, const char *thread_id)
141 {
142 xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
143 if (doc_ptr == NULL) {
144 return 0;
145 }
146 int result = find_thread_in_document(doc_ptr, thread_id) != NULL;
147 xmlFreeDoc(doc_ptr);
148 return result;
149 }
150