CBMC
xml_goto_trace.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Traces of GOTO Programs
4 
5 Author: 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/string_constant.h>
18 #include <util/symbol.h>
19 #include <util/xml_irep.h>
20 
21 #include <langapi/language_util.h>
22 
23 #include "goto_trace.h"
24 #include "printf_formatter.h"
25 #include "structured_trace_util.h"
26 #include "xml_expr.h"
27 
30 {
31  for(auto &op : expr.operands())
33 
34  if(expr.id() == ID_string_constant)
35  expr = to_string_constant(expr).to_array_expr();
36 }
37 
41 static std::string
42 get_printable_xml(const namespacet &ns, const irep_idt &id, const exprt &expr)
43 {
44  std::string result = from_expr(ns, id, expr);
45 
46  if(!xmlt::is_printable_xml(result))
47  {
48  exprt new_expr = expr;
50  result = from_expr(ns, id, new_expr);
51 
52  // give up
53  if(!xmlt::is_printable_xml(result))
54  return {};
55  }
56 
57  return result;
58 }
59 
61 {
62  xmlt value_xml{"full_lhs_value"};
63 
64  const exprt &value = step.full_lhs_value;
65  if(value.is_nil())
66  return value_xml;
67 
68  const auto &lhs_object = step.get_lhs_object();
69  const irep_idt identifier =
70  lhs_object.has_value() ? lhs_object->get_identifier() : irep_idt();
71  value_xml.data = get_printable_xml(ns, identifier, value);
72 
73  const auto &bv_type = type_try_dynamic_cast<bitvector_typet>(value.type());
74  const auto &constant = expr_try_dynamic_cast<constant_exprt>(value);
75  if(bv_type && constant)
76  {
77  const auto width = bv_type->get_width();
78  // It is fine to pass `false` into the `is_signed` parameter, even for
79  // signed values, because the subsequent conversion to binary will result
80  // in the same value either way. E.g. if the value is `-1` for a signed 8
81  // bit value, this will convert to `255` which is `11111111` in binary,
82  // which is the desired result.
83  const auto binary_representation =
84  integer2binary(bvrep2integer(constant->get_value(), width, false), width);
85  value_xml.set_attribute("binary", binary_representation);
86  }
87  return value_xml;
88 }
89 
90 void convert(
91  const namespacet &ns,
92  const goto_tracet &goto_trace,
93  xmlt &dest)
94 {
95  dest=xmlt("goto_trace");
96 
97  source_locationt previous_source_location;
98 
99  for(const auto &step : goto_trace.steps)
100  {
101  const source_locationt &source_location = step.pc->source_location();
102 
103  xmlt xml_location;
104  if(source_location.is_not_nil() && !source_location.get_file().empty())
105  xml_location=xml(source_location);
106 
107  switch(step.type)
108  {
110  if(!step.cond_value)
111  {
112  xmlt &xml_failure=dest.new_element("failure");
113 
114  xml_failure.set_attribute_bool("hidden", step.hidden);
115  xml_failure.set_attribute("thread", std::to_string(step.thread_nr));
116  xml_failure.set_attribute("step_nr", std::to_string(step.step_nr));
117  xml_failure.set_attribute("reason", id2string(step.comment));
118  xml_failure.set_attribute("property", id2string(step.property_id));
119 
120  if(!xml_location.name.empty())
121  xml_failure.new_element().swap(xml_location);
122  }
123  break;
124 
127  {
128  auto lhs_object = step.get_lhs_object();
129  irep_idt identifier =
130  lhs_object.has_value() ? lhs_object->get_identifier() : irep_idt();
131  xmlt &xml_assignment = dest.new_element("assignment");
132 
133  if(!xml_location.name.empty())
134  xml_assignment.new_element().swap(xml_location);
135 
136  {
137  const symbolt *symbol;
138 
139  if(
140  lhs_object.has_value() &&
141  !ns.lookup(lhs_object->get_identifier(), symbol))
142  {
143  std::string type_string =
144  from_type(ns, symbol->name, step.full_lhs.type());
145 
146  xml_assignment.set_attribute("mode", id2string(symbol->mode));
147  xml_assignment.set_attribute("identifier", id2string(symbol->name));
148  xml_assignment.set_attribute(
149  "base_name", id2string(symbol->base_name));
150  xml_assignment.set_attribute(
151  "display_name", id2string(symbol->display_name()));
152  xml_assignment.new_element("full_lhs_type").data = type_string;
153  }
154  }
155 
156  std::string full_lhs_string;
157 
158  if(step.full_lhs.is_not_nil())
159  full_lhs_string = get_printable_xml(ns, identifier, step.full_lhs);
160 
161  xml_assignment.new_element("full_lhs").data = full_lhs_string;
162  xml_assignment.new_element(full_lhs_value(step, ns));
163 
164  xml_assignment.set_attribute_bool("hidden", step.hidden);
165  xml_assignment.set_attribute("thread", std::to_string(step.thread_nr));
166  xml_assignment.set_attribute("step_nr", std::to_string(step.step_nr));
167 
168  xml_assignment.set_attribute(
169  "assignment_type",
170  step.assignment_type ==
172  ? "actual_parameter"
173  : "state");
174  break;
175  }
176 
178  {
179  printf_formattert printf_formatter(ns);
180  printf_formatter(id2string(step.format_string), step.io_args);
181  std::string text = printf_formatter.as_string();
182  xmlt &xml_output = dest.new_element("output");
183 
184  xml_output.new_element("text").data = text;
185 
186  xml_output.set_attribute_bool("hidden", step.hidden);
187  xml_output.set_attribute("thread", std::to_string(step.thread_nr));
188  xml_output.set_attribute("step_nr", std::to_string(step.step_nr));
189 
190  if(!xml_location.name.empty())
191  xml_output.new_element().swap(xml_location);
192 
193  for(const auto &arg : step.io_args)
194  {
195  xml_output.new_element("value").data =
196  get_printable_xml(ns, step.function_id, arg);
197  xml_output.new_element("value_expression").new_element(xml(arg, ns));
198  }
199  break;
200  }
201 
203  {
204  xmlt &xml_input = dest.new_element("input");
205  xml_input.new_element("input_id").data = id2string(step.io_id);
206 
207  xml_input.set_attribute_bool("hidden", step.hidden);
208  xml_input.set_attribute("thread", std::to_string(step.thread_nr));
209  xml_input.set_attribute("step_nr", std::to_string(step.step_nr));
210 
211  for(const auto &arg : step.io_args)
212  {
213  xml_input.new_element("value").data =
214  get_printable_xml(ns, step.function_id, arg);
215  xml_input.new_element("value_expression").new_element(xml(arg, ns));
216  }
217 
218  if(!xml_location.name.empty())
219  xml_input.new_element().swap(xml_location);
220  break;
221  }
222 
224  {
225  std::string tag = "function_call";
226  xmlt &xml_call_return = dest.new_element(tag);
227 
228  xml_call_return.set_attribute_bool("hidden", step.hidden);
229  xml_call_return.set_attribute("thread", std::to_string(step.thread_nr));
230  xml_call_return.set_attribute("step_nr", std::to_string(step.step_nr));
231 
232  const symbolt &symbol = ns.lookup(step.called_function);
233  xmlt &xml_function = xml_call_return.new_element("function");
234  xml_function.set_attribute(
235  "display_name", id2string(symbol.display_name()));
236  xml_function.set_attribute("identifier", id2string(symbol.name));
237  xml_function.new_element() = xml(symbol.location);
238 
239  if(!xml_location.name.empty())
240  xml_call_return.new_element().swap(xml_location);
241  break;
242  }
243 
245  {
246  std::string tag = "function_return";
247  xmlt &xml_call_return = dest.new_element(tag);
248 
249  xml_call_return.set_attribute_bool("hidden", step.hidden);
250  xml_call_return.set_attribute("thread", std::to_string(step.thread_nr));
251  xml_call_return.set_attribute("step_nr", std::to_string(step.step_nr));
252 
253  const symbolt &symbol = ns.lookup(step.called_function);
254  xmlt &xml_function = xml_call_return.new_element("function");
255  xml_function.set_attribute(
256  "display_name", id2string(symbol.display_name()));
257  xml_function.set_attribute("identifier", id2string(symbol.name));
258  xml_function.new_element() = xml(symbol.location);
259 
260  if(!xml_location.name.empty())
261  xml_call_return.new_element().swap(xml_location);
262  break;
263  }
264 
277  {
278  const auto default_step = ::default_step(step, previous_source_location);
279  if(default_step)
280  {
281  xmlt &xml_location_only =
283 
284  xml_location_only.set_attribute_bool("hidden", default_step->hidden);
285  xml_location_only.set_attribute(
286  "thread", std::to_string(default_step->thread_number));
287  xml_location_only.set_attribute(
288  "step_nr", std::to_string(default_step->step_number));
289 
290  xml_location_only.new_element(xml(default_step->location));
291  }
292 
293  break;
294  }
295  }
296 
297  if(source_location.is_not_nil() && !source_location.get_file().empty())
298  previous_source_location=source_location;
299  }
300 }
default_step
optionalt< default_trace_stept > default_step(const goto_trace_stept &step, const source_locationt &previous_source_location)
Definition: structured_trace_util.cpp:39
printf_formattert::as_string
std::string as_string()
Definition: printf_formatter.cpp:53
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
goto_trace_stept::typet::LOCATION
@ LOCATION
goto_trace_stept::full_lhs_value
exprt full_lhs_value
Definition: goto_trace.h:132
goto_trace_stept::get_lhs_object
optionalt< symbol_exprt > get_lhs_object() const
Definition: goto_trace.cpp:51
goto_trace_stept::typet::ASSUME
@ ASSUME
arith_tools.h
printf_formattert
Definition: printf_formatter.h:19
printf_formatter.h
symbolt::display_name
const irep_idt & display_name() const
Return language specific display name if present.
Definition: symbol.h:55
xmlt::is_printable_xml
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
convert
void convert(const namespacet &ns, const goto_tracet &goto_trace, xmlt &dest)
Definition: xml_goto_trace.cpp:90
default_step_name
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.
Definition: structured_trace_util.cpp:27
to_string_constant
const string_constantt & to_string_constant(const exprt &expr)
Definition: string_constant.h:40
goto_tracet::steps
stepst steps
Definition: goto_trace.h:178
string_constant.h
exprt
Base class for all expressions.
Definition: expr.h:55
xml_irep.h
symbolt::base_name
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
from_type
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
Definition: language_util.cpp:51
irep_idt
dstringt irep_idt
Definition: irep.h:37
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:58
goto_trace_stept
Step of the trace of a GOTO program.
Definition: goto_trace.h:49
goto_trace.h
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
goto_trace_stept::typet::OUTPUT
@ OUTPUT
goto_trace_stept::typet::FUNCTION_RETURN
@ FUNCTION_RETURN
symbolt::mode
irep_idt mode
Language mode.
Definition: symbol.h:49
goto_trace_stept::typet::DECL
@ DECL
get_printable_xml
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....
Definition: xml_goto_trace.cpp:42
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
xml
xmlt xml(const irep_idt &property_id, const property_infot &property_info)
Definition: properties.cpp:110
goto_trace_stept::typet::ASSERT
@ ASSERT
language_util.h
goto_trace_stept::typet::NONE
@ NONE
xmlt::name
std::string name
Definition: xml.h:39
xml_goto_trace.h
goto_trace_stept::typet::ASSIGNMENT
@ ASSIGNMENT
symbol.h
Symbol table entry.
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
dstringt::empty
bool empty() const
Definition: dstring.h:88
goto_trace_stept::assignment_typet::ACTUAL_PARAMETER
@ ACTUAL_PARAMETER
goto_trace_stept::typet::INPUT
@ INPUT
goto_trace_stept::typet::ATOMIC_END
@ ATOMIC_END
xmlt
Definition: xml.h:20
goto_trace_stept::typet::SPAWN
@ SPAWN
source_locationt
Definition: source_location.h:18
goto_trace_stept::typet::MEMORY_BARRIER
@ MEMORY_BARRIER
goto_trace_stept::typet::SHARED_WRITE
@ SHARED_WRITE
bvrep2integer
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
Definition: arith_tools.cpp:402
goto_trace_stept::typet::GOTO
@ GOTO
string_constantt::to_array_expr
array_exprt to_array_expr() const
convert string into array constant
Definition: string_constant.cpp:29
xmlt::set_attribute
void set_attribute(const std::string &attribute, unsigned value)
Definition: xml.cpp:198
symbolt::location
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
symbolt
Symbol table entry.
Definition: symbol.h:27
xmlt::set_attribute_bool
void set_attribute_bool(const std::string &attribute, bool value)
Definition: xml.h:72
goto_trace_stept::typet::ATOMIC_BEGIN
@ ATOMIC_BEGIN
full_lhs_value
xmlt full_lhs_value(const goto_trace_stept &step, const namespacet &ns)
Definition: xml_goto_trace.cpp:60
xmlt::swap
void swap(xmlt &xml)
Definition: xml.cpp:25
goto_tracet
Trace of a GOTO program.
Definition: goto_trace.h:174
source_locationt::get_file
const irep_idt & get_file() const
Definition: source_location.h:35
exprt::operands
operandst & operands()
Definition: expr.h:94
goto_trace_stept::typet::SHARED_READ
@ SHARED_READ
integer2binary
const std::string integer2binary(const mp_integer &n, std::size_t width)
Definition: mp_arith.cpp:64
structured_trace_util.h
goto_trace_stept::typet::FUNCTION_CALL
@ FUNCTION_CALL
xmlt::data
std::string data
Definition: xml.h:39
replace_string_constants_rec
static void replace_string_constants_rec(exprt &expr)
Rewrite all string constants to their array counterparts.
Definition: xml_goto_trace.cpp:29
from_expr
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
Definition: language_util.cpp:38
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
xml_expr.h
xmlt::new_element
xmlt & new_element(const std::string &key)
Definition: xml.h:95
goto_trace_stept::typet::DEAD
@ DEAD
goto_trace_stept::typet::CONSTRAINT
@ CONSTRAINT