CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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>
17#include <util/namespace.h>
19#include <util/symbol.h>
20#include <util/xml_irep.h>
21
24
25#include "goto_trace.h"
27#include "xml_expr.h"
28
31{
32 for(auto &op : expr.operands())
34
35 if(expr.id() == ID_string_constant)
36 expr = to_string_constant(expr).to_array_expr();
37}
38
42static std::string
43get_printable_xml(const namespacet &ns, const irep_idt &id, const exprt &expr)
44{
45 std::string result = from_expr(ns, id, expr);
46
47 if(!xmlt::is_printable_xml(result))
48 {
49 exprt new_expr = expr;
51 result = from_expr(ns, id, new_expr);
52
53 // give up
54 if(!xmlt::is_printable_xml(result))
55 return {};
56 }
57
58 return result;
59}
60
62{
63 xmlt value_xml{"full_lhs_value"};
64
65 const exprt &value = step.full_lhs_value;
66 if(value.is_nil())
67 return value_xml;
68
69 const auto &lhs_object = step.get_lhs_object();
70 const irep_idt identifier =
71 lhs_object.has_value() ? lhs_object->get_identifier() : irep_idt();
72 value_xml.data = get_printable_xml(ns, identifier, value);
73
75 const auto &constant = expr_try_dynamic_cast<constant_exprt>(value);
76 if(bv_type && constant)
77 {
78 const auto width = bv_type->get_width();
79 // It is fine to pass `false` into the `is_signed` parameter, even for
80 // signed values, because the subsequent conversion to binary will result
81 // in the same value either way. E.g. if the value is `-1` for a signed 8
82 // bit value, this will convert to `255` which is `11111111` in binary,
83 // which is the desired result.
84 const auto binary_representation =
85 integer2binary(bvrep2integer(constant->get_value(), width, false), width);
86 value_xml.set_attribute("binary", binary_representation);
87 }
88 return value_xml;
89}
90
92 const namespacet &ns,
94 xmlt &dest)
95{
96 dest=xmlt("goto_trace");
97
99
100 for(const auto &step : goto_trace.steps)
101 {
102 const source_locationt &source_location = step.pc->source_location();
103
105 if(source_location.is_not_nil() && !source_location.get_file().empty())
106 xml_location=xml(source_location);
107
108 switch(step.type)
109 {
111 if(!step.cond_value)
112 {
113 xmlt &xml_failure=dest.new_element("failure");
114
115 xml_failure.set_attribute_bool("hidden", step.hidden);
116 xml_failure.set_attribute("thread", std::to_string(step.thread_nr));
117 xml_failure.set_attribute("step_nr", std::to_string(step.step_nr));
118 xml_failure.set_attribute("reason", id2string(step.comment));
119 xml_failure.set_attribute("property", id2string(step.property_id));
120
121 if(!xml_location.name.empty())
122 xml_failure.new_element().swap(xml_location);
123 }
124 break;
125
128 {
129 auto lhs_object = step.get_lhs_object();
130 irep_idt identifier =
131 lhs_object.has_value() ? lhs_object->get_identifier() : irep_idt();
132 xmlt &xml_assignment = dest.new_element("assignment");
133
134 if(!xml_location.name.empty())
135 xml_assignment.new_element().swap(xml_location);
136
137 {
138 const symbolt *symbol;
139
140 if(
141 lhs_object.has_value() &&
142 !ns.lookup(lhs_object->get_identifier(), symbol))
143 {
144 std::string type_string =
145 from_type(ns, symbol->name, step.full_lhs.type());
146
147 xml_assignment.set_attribute("mode", id2string(symbol->mode));
148 xml_assignment.set_attribute("identifier", id2string(symbol->name));
149 xml_assignment.set_attribute(
150 "base_name", id2string(symbol->base_name));
151 xml_assignment.set_attribute(
152 "display_name", id2string(symbol->display_name()));
153 xml_assignment.new_element("full_lhs_type").data = type_string;
154 }
155 }
156
157 std::string full_lhs_string;
158
159 if(step.full_lhs.is_not_nil())
160 full_lhs_string = get_printable_xml(ns, identifier, step.full_lhs);
161
162 xml_assignment.new_element("full_lhs").data = full_lhs_string;
163 xml_assignment.new_element(full_lhs_value(step, ns));
164
165 xml_assignment.set_attribute_bool("hidden", step.hidden);
166 xml_assignment.set_attribute("thread", std::to_string(step.thread_nr));
167 xml_assignment.set_attribute("step_nr", std::to_string(step.step_nr));
168
169 xml_assignment.set_attribute(
170 "assignment_type",
171 step.assignment_type ==
173 ? "actual_parameter"
174 : "state");
175 break;
176 }
177
179 {
181 printf_formatter(id2string(step.format_string), step.io_args);
182 std::string text = printf_formatter.as_string();
183 xmlt &xml_output = dest.new_element("output");
184
185 xml_output.new_element("text").data = text;
186
187 xml_output.set_attribute_bool("hidden", step.hidden);
188 xml_output.set_attribute("thread", std::to_string(step.thread_nr));
189 xml_output.set_attribute("step_nr", std::to_string(step.step_nr));
190
191 if(!xml_location.name.empty())
192 xml_output.new_element().swap(xml_location);
193
194 for(const auto &arg : step.io_args)
195 {
196 xml_output.new_element("value").data =
197 get_printable_xml(ns, step.function_id, arg);
198 xml_output.new_element("value_expression").new_element(xml(arg, ns));
199 }
200 break;
201 }
202
204 {
205 xmlt &xml_input = dest.new_element("input");
206 xml_input.new_element("input_id").data = id2string(step.io_id);
207
208 xml_input.set_attribute_bool("hidden", step.hidden);
209 xml_input.set_attribute("thread", std::to_string(step.thread_nr));
210 xml_input.set_attribute("step_nr", std::to_string(step.step_nr));
211
212 for(const auto &arg : step.io_args)
213 {
214 xml_input.new_element("value").data =
215 get_printable_xml(ns, step.function_id, arg);
216 xml_input.new_element("value_expression").new_element(xml(arg, ns));
217 }
218
219 if(!xml_location.name.empty())
220 xml_input.new_element().swap(xml_location);
221 break;
222 }
223
225 {
226 std::string tag = "function_call";
227 xmlt &xml_call_return = dest.new_element(tag);
228
229 xml_call_return.set_attribute_bool("hidden", step.hidden);
230 xml_call_return.set_attribute("thread", std::to_string(step.thread_nr));
231 xml_call_return.set_attribute("step_nr", std::to_string(step.step_nr));
232
233 const symbolt &symbol = ns.lookup(step.called_function);
234 xmlt &xml_function = xml_call_return.new_element("function");
235 xml_function.set_attribute(
236 "display_name", id2string(symbol.display_name()));
237 xml_function.set_attribute("identifier", id2string(symbol.name));
238 xml_function.new_element() = xml(symbol.location);
239
240 if(!xml_location.name.empty())
241 xml_call_return.new_element().swap(xml_location);
242 break;
243 }
244
246 {
247 std::string tag = "function_return";
248 xmlt &xml_call_return = dest.new_element(tag);
249
250 xml_call_return.set_attribute_bool("hidden", step.hidden);
251 xml_call_return.set_attribute("thread", std::to_string(step.thread_nr));
252 xml_call_return.set_attribute("step_nr", std::to_string(step.step_nr));
253
254 const symbolt &symbol = ns.lookup(step.called_function);
255 xmlt &xml_function = xml_call_return.new_element("function");
256 xml_function.set_attribute(
257 "display_name", id2string(symbol.display_name()));
258 xml_function.set_attribute("identifier", id2string(symbol.name));
259 xml_function.new_element() = xml(symbol.location);
260
261 if(!xml_location.name.empty())
262 xml_call_return.new_element().swap(xml_location);
263 break;
264 }
265
278 {
280 if(default_step)
281 {
284
285 xml_location_only.set_attribute_bool("hidden", default_step->hidden);
286 xml_location_only.set_attribute(
287 "thread", std::to_string(default_step->thread_number));
288 xml_location_only.set_attribute(
289 "step_nr", std::to_string(default_step->step_number));
290
291 xml_location_only.new_element(xml(default_step->location));
292 }
293
294 break;
295 }
296 }
297
298 if(source_location.is_not_nil() && !source_location.get_file().empty())
299 previous_source_location=source_location;
300 }
301}
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
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:56
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
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.