CBMC
interrupt.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Interrupt Instrumentation
4 
5 Author: Daniel Kroening
6 
7 Date: September 2011
8 
9 \*******************************************************************/
10 
13 
14 #include "interrupt.h"
15 
16 #include <util/range.h>
17 #include <util/std_code.h>
18 
20 
21 #ifdef LOCAL_MAY
23 #endif
24 
25 #include "rw_set.h"
26 
28  const rw_set_baset &code_rw_set,
29  const rw_set_baset &isr_rw_set)
30 {
31  // R/W race?
32  for(const auto &r_entry : code_rw_set.r_entries)
33  {
34  if(isr_rw_set.has_w_entry(r_entry.first))
35  return true;
36  }
37 
38  return false;
39 }
40 
42  const rw_set_baset &code_rw_set,
43  const rw_set_baset &isr_rw_set)
44 {
45  // W/R or W/W?
46  for(const auto &w_entry : code_rw_set.w_entries)
47  {
48  if(isr_rw_set.has_r_entry(w_entry.first))
49  return true;
50 
51  if(isr_rw_set.has_w_entry(w_entry.first))
52  return true;
53  }
54 
55  return false;
56 }
57 
58 static void interrupt(
59  value_setst &value_sets,
60  const symbol_tablet &symbol_table,
61  const irep_idt &function_id,
62 #ifdef LOCAL_MAY
63  const goto_functionst::goto_functiont &goto_function,
64 #endif
65  goto_programt &goto_program,
66  const symbol_exprt &interrupt_handler,
67  const rw_set_baset &isr_rw_set,
68  message_handlert &message_handler)
69 {
70  namespacet ns(symbol_table);
71 
72  Forall_goto_program_instructions(i_it, goto_program)
73  {
74  goto_programt::instructiont &instruction=*i_it;
75 
76 #ifdef LOCAL_MAY
77  local_may_aliast local_may(goto_function);
78 #endif
79  rw_set_loct rw_set(
80  ns,
81  value_sets,
82  function_id,
83  i_it,
84 #ifdef LOCAL_MAY
85  local_may,
86 #endif
87  message_handler); // NOLINT(whitespace/parens)
88 
89  // potential race?
90  bool race_on_read=potential_race_on_read(rw_set, isr_rw_set);
91  bool race_on_write=potential_race_on_write(rw_set, isr_rw_set);
92 
93  if(!race_on_read && !race_on_write)
94  continue;
95 
96  // Insert the call to the ISR.
97  // We do before for races on Read, and before and after
98  // for races on Write.
99 
100  if(race_on_read || race_on_write)
101  {
102  goto_programt::instructiont original_instruction;
103  original_instruction.swap(instruction);
104 
105  const source_locationt &source_location =
106  original_instruction.source_location();
107 
108  code_function_callt isr_call(interrupt_handler);
109  isr_call.add_source_location()=source_location;
110 
111  goto_programt::targett t_goto=i_it;
112  goto_programt::targett t_call=goto_program.insert_after(t_goto);
113  goto_programt::targett t_orig=goto_program.insert_after(t_call);
114 
115  *t_goto = goto_programt::make_goto(
116  t_orig,
117  side_effect_expr_nondett(bool_typet(), source_location),
118  source_location);
119 
120  *t_call = goto_programt::make_function_call(isr_call, source_location);
121 
122  t_orig->swap(original_instruction);
123 
124  i_it=t_orig; // the for loop already counts us up
125  }
126 
127  if(race_on_write)
128  {
129  // insert _after_ the instruction with race
130  goto_programt::targett t_orig=i_it;
131  t_orig++;
132 
133  const source_locationt &source_location = i_it->source_location();
134 
135  code_function_callt isr_call(interrupt_handler);
136  isr_call.add_source_location()=source_location;
137 
138  goto_programt::targett t_goto = goto_program.insert_after(
139  i_it,
141  t_orig,
142  side_effect_expr_nondett(bool_typet(), source_location),
143  source_location));
144 
145  goto_programt::targett t_call = goto_program.insert_after(
146  t_goto, goto_programt::make_function_call(isr_call, source_location));
147 
148  i_it=t_call; // the for loop already counts us up
149  }
150  }
151 }
152 
153 static symbol_exprt
154 get_isr(const symbol_tablet &symbol_table, const irep_idt &interrupt_handler)
155 {
156  std::list<symbol_exprt> matches;
157 
158  for(const auto &symbol_name_entry :
159  equal_range(symbol_table.symbol_base_map, interrupt_handler))
160  {
161  // look it up
162  symbol_tablet::symbolst::const_iterator s_it =
163  symbol_table.symbols.find(symbol_name_entry.second);
164 
165  if(s_it==symbol_table.symbols.end())
166  continue;
167 
168  if(s_it->second.type.id() == ID_code && !s_it->second.is_property)
169  matches.push_back(s_it->second.symbol_expr());
170  }
171 
172  if(matches.empty())
173  throw "interrupt handler '" + id2string(interrupt_handler) + "' not found";
174 
175  if(matches.size()>=2)
176  throw "interrupt handler '" + id2string(interrupt_handler) +
177  "' is ambiguous";
178 
179  symbol_exprt isr=matches.front();
180 
181  if(!to_code_type(isr.type()).parameters().empty())
182  throw "interrupt handler '" + id2string(interrupt_handler) +
183  "' must not have parameters";
184 
185  return isr;
186 }
187 
189  value_setst &value_sets,
190  goto_modelt &goto_model,
191  const irep_idt &interrupt_handler,
192  message_handlert &message_handler)
193 {
194  // look up the ISR
195  symbol_exprt isr=
196  get_isr(goto_model.symbol_table, interrupt_handler);
197 
198  // we first figure out which objects are read/written by the ISR
199  rw_set_functiont isr_rw_set(value_sets, goto_model, isr, message_handler);
200 
201  // now instrument
202 
203  for(auto &gf_entry : goto_model.goto_functions.function_map)
204  {
205  if(
206  gf_entry.first != INITIALIZE_FUNCTION &&
207  gf_entry.first != goto_functionst::entry_point() &&
208  gf_entry.first != isr.get_identifier())
209  {
210  interrupt(
211  value_sets,
212  goto_model.symbol_table,
213  gf_entry.first,
214 #ifdef LOCAL_MAY
215  gf_entry.second,
216 #endif
217  gf_entry.second.body,
218  isr,
219  isr_rw_set,
220  message_handler);
221  }
222  }
223 
224  goto_model.goto_functions.update();
225 }
The Boolean type.
Definition: std_types.h:36
goto_instruction_codet representation of a function call statement.
const parameterst & parameters() const
Definition: std_types.h:699
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
source_locationt & add_source_location()
Definition: expr.h:236
typet & type()
Return the type of the expression.
Definition: expr.h:84
function_mapt function_map
::goto_functiont goto_functiont
static irep_idt entry_point()
Get the identifier of the entry point to a goto model.
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:181
const source_locationt & source_location() const
Definition: goto_program.h:333
void swap(instructiont &instruction)
Swap two instructions.
Definition: goto_program.h:541
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
instructionst::iterator targett
Definition: goto_program.h:614
static instructiont make_function_call(const code_function_callt &_code, const source_locationt &l=source_locationt::nil())
Create a function call instruction.
static instructiont make_goto(targett _target, const source_locationt &l=source_locationt::nil())
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
entriest r_entries
Definition: rw_set.h:60
bool has_w_entry(irep_idt object) const
Definition: rw_set.h:80
bool has_r_entry(irep_idt object) const
Definition: rw_set.h:85
entriest w_entries
Definition: rw_set.h:60
A side_effect_exprt that returns a non-deterministically chosen value.
Definition: std_code.h:1520
Expression to hold a symbol (variable)
Definition: std_expr.h:131
const irep_idt & get_identifier() const
Definition: std_expr.h:160
const symbol_base_mapt & symbol_base_map
Read-only field, used to look up symbol names given their base names.
const symbolst & symbols
Read-only field, used to look up symbols given their names.
The symbol table.
Definition: symbol_table.h:14
#define Forall_goto_program_instructions(it, program)
static bool potential_race_on_read(const rw_set_baset &code_rw_set, const rw_set_baset &isr_rw_set)
Definition: interrupt.cpp:27
static bool potential_race_on_write(const rw_set_baset &code_rw_set, const rw_set_baset &isr_rw_set)
Definition: interrupt.cpp:41
static void interrupt(value_setst &value_sets, const symbol_tablet &symbol_table, const irep_idt &function_id, goto_programt &goto_program, const symbol_exprt &interrupt_handler, const rw_set_baset &isr_rw_set, message_handlert &message_handler)
Definition: interrupt.cpp:58
static symbol_exprt get_isr(const symbol_tablet &symbol_table, const irep_idt &interrupt_handler)
Definition: interrupt.cpp:154
Interrupt Instrumentation for Goto Programs.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
Field-insensitive, location-sensitive may-alias analysis.
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< typename multimapt::const_iterator > equal_range(const multimapt &multimap, const typename multimapt::key_type &key)
Utility function to make equal_range method of multimap easier to use by returning a ranget object.
Definition: range.h:539
Race Detection for Threaded Goto Programs.
#define INITIALIZE_FUNCTION
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788