CBMC
Loading...
Searching...
No Matches
xml_goto_trace.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Traces of GOTO Programs
4
5Author: Daniel Kroening
6
7 Date: November 2005
8
9\*******************************************************************/
10
13
14#include "xml_goto_trace.h"
15
16#include <util/arith_tools.h>
18#include <util/namespace.h>
20#include <util/symbol.h>
21#include <util/xml_irep.h>
22
25
26#include "goto_trace.h"
28#include "xml_expr.h"
29
32{
33 for(auto &op : expr.operands())
35
36 if(expr.id() == ID_string_constant)
37 expr = to_string_constant(expr).to_array_expr();
38}
39
43static std::string
44get_printable_xml(const namespacet &ns, const irep_idt &id, const exprt &expr)
45{
46 std::string result = from_expr(ns, id, expr);
47
48 if(!xmlt::is_printable_xml(result))
49 {
50 exprt new_expr = expr;
52 result = from_expr(ns, id, new_expr);
53
54 // give up
55 if(!xmlt::is_printable_xml(result))
56 return {};
57 }
58
59 return result;
60}
61
63{
64 xmlt value_xml{"full_lhs_value"};
65
66 const exprt &value = step.full_lhs_value;
67 if(value.is_nil())
68 return value_xml;
69
70 const auto &lhs_object = step.get_lhs_object();
71 const irep_idt identifier =
72 lhs_object.has_value() ? lhs_object->identifier() : irep_idt();
73 value_xml.data = get_printable_xml(ns, identifier, value);
74
76 const auto &constant = expr_try_dynamic_cast<constant_exprt>(value);
77 if(bv_type && constant)
78 {
79 const auto width = bv_type->get_width();
80 // It is fine to pass `false` into the `is_signed` parameter, even for
81 // signed values, because the subsequent conversion to binary will result
82 // in the same value either way. E.g. if the value is `-1` for a signed 8
83 // bit value, this will convert to `255` which is `11111111` in binary,
84 // which is the desired result.
85 const auto binary_representation =
86 integer2binary(bvrep2integer(constant->get_value(), width, false), width);
87 value_xml.set_attribute("binary", binary_representation);
88 }
89 return value_xml;
90}
91
93 const namespacet &ns,
95 xmlt &dest)
96{
97 dest=xmlt("goto_trace");
98
100
101 for(const auto &step : goto_trace.steps)
102 {
103 const source_locationt &source_location = step.pc->source_location();
104
106 if(source_location.is_not_nil() && !source_location.get_file().empty())
107 xml_location=xml(source_location);
108
109 switch(step.type)
110 {
112 if(!step.cond_value)
113 {
114 xmlt &xml_failure=dest.new_element("failure");
115
116 xml_failure.set_attribute_bool("hidden", step.hidden);
117 xml_failure.set_attribute("thread", std::to_string(step.thread_nr));
118 xml_failure.set_attribute("step_nr", std::to_string(step.step_nr));
119 xml_failure.set_attribute("reason", id2string(step.comment));
120 xml_failure.set_attribute("property", id2string(step.property_id));
121
122 if(!xml_location.name.empty())
123 xml_failure.new_element().swap(xml_location);
124 }
125 break;
126
129 {
130 auto lhs_object = step.get_lhs_object();
131 irep_idt identifier =
132 lhs_object.has_value() ? lhs_object->identifier() : irep_idt();
133 xmlt &xml_assignment = dest.new_element("assignment");
134
135 if(!xml_location.name.empty())
136 xml_assignment.new_element().swap(xml_location);
137
138 {
139 const symbolt *symbol;
140
141 if(
142 lhs_object.has_value() &&
143 !ns.lookup(lhs_object->identifier(), symbol))
144 {
145 std::string type_string =
146 from_type(ns, symbol->name, step.full_lhs.type());
147
148 xml_assignment.set_attribute("mode", id2string(symbol->mode));
149 xml_assignment.set_attribute("identifier", id2string(symbol->name));
150 xml_assignment.set_attribute(
151 "base_name", id2string(symbol->base_name));
152 xml_assignment.set_attribute(
153 "display_name", id2string(symbol->display_name()));
154 xml_assignment.new_element("full_lhs_type").data = type_string;
155 }
156 }
157
158 std::string full_lhs_string;
159
160 if(step.full_lhs.is_not_nil())
161 full_lhs_string = get_printable_xml(ns, identifier, step.full_lhs);
162
163 xml_assignment.new_element("full_lhs").data = full_lhs_string;
164 xml_assignment.new_element(full_lhs_value(step, ns));
165
166 xml_assignment.set_attribute_bool("hidden", step.hidden);
167 xml_assignment.set_attribute("thread", std::to_string(step.thread_nr));
168 xml_assignment.set_attribute("step_nr", std::to_string(step.step_nr));
169
170 xml_assignment.set_attribute(
171 "assignment_type",
172 step.assignment_type ==
174 ? "actual_parameter"
175 : "state");
176 break;
177 }
178
180 {
182 printf_formatter(id2string(step.format_string), step.io_args);
183 std::string text = printf_formatter.as_string();
184 xmlt &xml_output = dest.new_element("output");
185
186 xml_output.new_element("text").data = text;
187
188 xml_output.set_attribute_bool("hidden", step.hidden);
189 xml_output.set_attribute("thread", std::to_string(step.thread_nr));
190 xml_output.set_attribute("step_nr", std::to_string(step.step_nr));
191
192 if(!xml_location.name.empty())
193 xml_output.new_element().swap(xml_location);
194
195 for(const auto &arg : step.io_args)
196 {
197 xml_output.new_element("value").data =
198 get_printable_xml(ns, step.function_id, arg);
199 xml_output.new_element("value_expression").new_element(xml(arg, ns));
200 }
201 break;
202 }
203
205 {
206 xmlt &xml_input = dest.new_element("input");
207 xml_input.new_element("input_id").data = id2string(step.io_id);
208
209 xml_input.set_attribute_bool("hidden", step.hidden);
210 xml_input.set_attribute("thread", std::to_string(step.thread_nr));
211 xml_input.set_attribute("step_nr", std::to_string(step.step_nr));
212
213 for(const auto &arg : step.io_args)
214 {
215 xml_input.new_element("value").data =
216 get_printable_xml(ns, step.function_id, arg);
217 xml_input.new_element("value_expression").new_element(xml(arg, ns));
218 }
219
220 if(!xml_location.name.empty())
221 xml_input.new_element().swap(xml_location);
222 break;
223 }
224
226 {
227 std::string tag = "function_call";
228 xmlt &xml_call_return = dest.new_element(tag);
229
230 xml_call_return.set_attribute_bool("hidden", step.hidden);
231 xml_call_return.set_attribute("thread", std::to_string(step.thread_nr));
232 xml_call_return.set_attribute("step_nr", std::to_string(step.step_nr));
233
234 const symbolt &symbol = ns.lookup(step.called_function);
235 xmlt &xml_function = xml_call_return.new_element("function");
236 xml_function.set_attribute(
237 "display_name", id2string(symbol.display_name()));
238 xml_function.set_attribute("identifier", id2string(symbol.name));
239 xml_function.new_element() = xml(symbol.location);
240
241 if(!xml_location.name.empty())
242 xml_call_return.new_element().swap(xml_location);
243 break;
244 }
245
247 {
248 std::string tag = "function_return";
249 xmlt &xml_call_return = dest.new_element(tag);
250
251 xml_call_return.set_attribute_bool("hidden", step.hidden);
252 xml_call_return.set_attribute("thread", std::to_string(step.thread_nr));
253 xml_call_return.set_attribute("step_nr", std::to_string(step.step_nr));
254
255 const symbolt &symbol = ns.lookup(step.called_function);
256 xmlt &xml_function = xml_call_return.new_element("function");
257 xml_function.set_attribute(
258 "display_name", id2string(symbol.display_name()));
259 xml_function.set_attribute("identifier", id2string(symbol.name));
260 xml_function.new_element() = xml(symbol.location);
261
262 if(!xml_location.name.empty())
263 xml_call_return.new_element().swap(xml_location);
264 break;
265 }
266
279 {
281 if(default_step)
282 {
285
286 xml_location_only.set_attribute_bool("hidden", default_step->hidden);
287 xml_location_only.set_attribute(
288 "thread", std::to_string(default_step->thread_number));
289 xml_location_only.set_attribute(
290 "step_nr", std::to_string(default_step->step_number));
291
292 xml_location_only.new_element(xml(default_step->location));
293 }
294
295 break;
296 }
297 }
298
299 if(source_location.is_not_nil() && !source_location.get_file().empty())
300 previous_source_location=source_location;
301 }
302}
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
Pre-defined bitvector types.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:57
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
Step of the trace of a GOTO program.
Definition goto_trace.h:50
std::optional< symbol_exprt > get_lhs_object() const
Trace of a GOTO program.
Definition goto_trace.h:177
bool is_not_nil() const
Definition irep.h:372
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
const irep_idt & get_file() const
Symbol table entry.
Definition symbol.h:28
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
irep_idt name
The unique identifier.
Definition symbol.h:40
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
const irep_idt & display_name() const
Return language specific display name if present.
Definition symbol.h:55
irep_idt mode
Language mode.
Definition symbol.h:49
Definition xml.h:21
xmlt & new_element(const std::string &key)
Definition xml.h:95
static bool is_printable_xml(const std::string &s)
Determine whether s does not contain any characters that cannot be escaped in XML 1....
Definition xml.cpp:160
Traces of GOTO Programs.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
const std::string integer2binary(const mp_integer &n, std::size_t width)
Definition mp_arith.cpp:64
printf Formatting
xmlt xml(const irep_idt &property_id, const property_infot &property_info)
const string_constantt & to_string_constant(const exprt &expr)
std::string default_step_name(const default_step_kindt &step_type)
Turns a default_step_kindt into a string that can be used in the trace.
std::optional< default_trace_stept > default_step(const goto_trace_stept &step, const source_locationt &previous_source_location)
Utilities for printing location info steps in the trace in a format agnostic way.
Symbol table entry.
dstringt irep_idt
xmlt full_lhs_value(const goto_trace_stept &step, const namespacet &ns)
static std::string get_printable_xml(const namespacet &ns, const irep_idt &id, const exprt &expr)
Given an expression expr, produce a string representation that is printable in XML 1....
static void replace_string_constants_rec(exprt &expr)
Rewrite all string constants to their array counterparts.
void convert(const namespacet &ns, const goto_tracet &goto_trace, xmlt &dest)
Traces of GOTO Programs.