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/namespace.h>
18 #include <util/string_constant.h>
19 #include <util/symbol.h>
20 #include <util/xml_irep.h>
21 
22 #include <langapi/language_util.h>
23 
24 #include "goto_trace.h"
25 #include "printf_formatter.h"
26 #include "structured_trace_util.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 
42 static std::string
43 get_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 
74  const auto &bv_type = type_try_dynamic_cast<bitvector_typet>(value.type());
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 
91 void convert(
92  const namespacet &ns,
93  const goto_tracet &goto_trace,
94  xmlt &dest)
95 {
96  dest=xmlt("goto_trace");
97 
98  source_locationt previous_source_location;
99 
100  for(const auto &step : goto_trace.steps)
101  {
102  const source_locationt &source_location = step.pc->source_location();
103 
104  xmlt xml_location;
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  {
180  printf_formattert printf_formatter(ns);
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  {
279  const auto default_step = ::default_step(step, previous_source_location);
280  if(default_step)
281  {
282  xmlt &xml_location_only =
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
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool empty() const
Definition: dstring.h:89
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
exprt full_lhs_value
Definition: goto_trace.h:133
std::optional< symbol_exprt > get_lhs_object() const
Definition: goto_trace.cpp:53
Trace of a GOTO program.
Definition: goto_trace.h:177
stepst steps
Definition: goto_trace.h:180
bool is_not_nil() const
Definition: irep.h:368
const irep_idt & id() const
Definition: irep.h:384
bool is_nil() const
Definition: irep.h:364
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
std::string as_string()
const irep_idt & get_file() const
array_exprt to_array_expr() const
convert string into array constant
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
const irep_idt & display_name() const
Return language specific display name if present.
Definition: symbol.h:55
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 mode
Language mode.
Definition: symbol.h:49
Definition: xml.h:21
void set_attribute_bool(const std::string &attribute, bool value)
Definition: xml.h:72
void set_attribute(const std::string &attribute, unsigned value)
Definition: xml.cpp:198
void swap(xmlt &xml)
Definition: xml.cpp:25
xmlt & new_element(const std::string &key)
Definition: xml.h:95
std::string data
Definition: xml.h:39
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
std::string name
Definition: xml.h:39
Traces of GOTO Programs.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
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)
Definition: properties.cpp:110
const string_constantt & to_string_constant(const exprt &expr)
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
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.