CBMC
java_bytecode_convert_method_class.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: JAVA Bytecode Language Conversion
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #ifndef CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_CLASS_H
13 #define CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_CLASS_H
14 
16 
17 #include <util/expanding_vector.h>
18 #include <util/message.h>
19 #include <util/namespace.h>
20 #include <util/std_code.h>
21 #include <util/std_expr.h>
22 
24 
25 #include "ci_lazy_methods_needed.h"
27 
28 #include <list>
29 #include <vector>
30 
31 class class_hierarchyt;
32 class prefix_filtert;
33 class symbolt;
34 
36 {
37 public:
40  message_handlert &_message_handler,
41  size_t _max_array_length,
43  std::optional<ci_lazy_methods_neededt> needed_lazy_methods,
44  java_string_library_preprocesst &_string_preprocess,
46  bool threading_support,
48  : log(_message_handler),
51  max_array_length(_max_array_length),
56  string_preprocess(_string_preprocess),
58  method_has_this(false),
60  {
61  }
62 
68 
69  void operator()(
70  const symbolt &class_symbol,
71  const methodt &method,
72  const std::optional<prefix_filtert> &method_context)
73  {
74  convert(class_symbol, method, method_context);
75  }
76 
77  typedef uint16_t method_offsett;
78 
79 protected:
83  const size_t max_array_length;
86  const bool threading_support;
87  std::optional<ci_lazy_methods_neededt> needed_lazy_methods;
88 
93 
96 
100 
102 
107 
108 public:
109  struct holet
110  {
113  };
114 
116  {
119  std::vector<holet> holes;
120  };
121 
122  typedef std::vector<local_variable_with_holest>
124 
125  class variablet
126  {
127  public:
129  size_t start_pc;
130  size_t length;
131  bool is_parameter = false;
132  std::vector<holet> holes;
133 
135  const symbol_exprt &_symbol_expr,
136  std::size_t _start_pc,
137  std::size_t _length)
138  : symbol_expr(_symbol_expr), start_pc(_start_pc), length(_length)
139  {
140  }
141 
143  const symbol_exprt &_symbol_expr,
144  std::size_t _start_pc,
145  std::size_t _length,
146  bool _is_parameter)
147  : symbol_expr(_symbol_expr),
148  start_pc(_start_pc),
149  length(_length),
150  is_parameter(_is_parameter)
151  {
152  }
153 
155  const symbol_exprt &_symbol_expr,
156  std::size_t _start_pc,
157  std::size_t _length,
158  bool _is_parameter,
159  std::vector<holet> &&_holes)
160  : symbol_expr(_symbol_expr),
161  start_pc(_start_pc),
162  length(_length),
163  is_parameter(_is_parameter),
164  holes(std::move(_holes))
165  {
166  }
167  };
168 
169 protected:
170  typedef std::vector<variablet> variablest;
172  std::set<symbol_exprt> used_local_names;
174  std::map<irep_idt, bool> class_has_clinit_method;
175  std::map<irep_idt, bool> any_superclass_has_clinit_method;
177 
179  {
181  INST_INDEX_CONST = 3
182  };
183 
184  // return corresponding reference of variable
185  const variablet &find_variable_for_slot(
186  size_t address,
187  variablest &var_list);
188 
189  // JVM local variables
191  {
193  NO_CAST
194  };
195 
196  exprt variable(const exprt &arg, char type_char, size_t address);
197 
198  // temporary variables
199  std::list<symbol_exprt> tmp_vars;
200 
201  symbol_exprt tmp_variable(const std::string &prefix, const typet &type);
202 
203  // JVM program locations
204  static irep_idt label(const irep_idt &address);
205 
206  // JVM Stack
207  typedef std::vector<exprt> stackt;
209 
210  exprt::operandst pop(std::size_t n);
211 
212  void pop_residue(std::size_t n);
213 
214  void push(const exprt::operandst &o);
215 
220  {
221  return v.index < slots_for_parameters;
222  }
223 
225  {
227  const instructionst::const_iterator &it,
228  const codet &_code)
229  : source(it), code(_code), done(false)
230  {
231  }
232 
233  instructionst::const_iterator source;
234  std::list<method_offsett> successors;
235  std::set<method_offsett> predecessors;
238  bool done;
239  };
240 
241 public:
242  typedef std::map<method_offsett, converted_instructiont> address_mapt;
244  {
246  : method_with_amap(m, a)
247  {
248  }
249 
250  std::pair<const methodt &, const address_mapt &> method_with_amap;
251 
252  struct target_less_than // NOLINT(readability/identifiers)
253  {
254  bool operator()(const method_offsett &a, const method_offsett &b) const
255  {
256  return a < b;
257  }
258  };
259  };
262 
263 protected:
264  void find_initializers(
266  const address_mapt &amap,
267  const java_cfg_dominatorst &doms);
268 
270  local_variable_table_with_holest::iterator firstvar,
271  local_variable_table_with_holest::iterator varlimit,
272  const address_mapt &amap,
273  const java_cfg_dominatorst &doms);
274 
275  void setup_local_variables(const methodt &m, const address_mapt &amap);
276 
278  {
279  bool leaf;
280  std::vector<method_offsett> branch_addresses;
281  std::vector<block_tree_nodet> branch;
282 
284  {
285  }
286 
287  explicit block_tree_nodet(bool l) : leaf(l)
288  {
289  }
290 
292  {
293  return block_tree_nodet(true);
294  }
295  };
296 
297  static void replace_goto_target(
298  codet &repl,
299  const irep_idt &old_label,
300  const irep_idt &new_label);
301 
303  block_tree_nodet &tree,
304  code_blockt &this_block,
305  method_offsett address_start,
306  method_offsett address_limit,
307  method_offsett next_block_start_address);
308 
310  block_tree_nodet &tree,
311  code_blockt &this_block,
312  method_offsett address_start,
313  method_offsett address_limit,
314  method_offsett next_block_start_address,
315  const address_mapt &amap,
316  bool allow_merge = true);
317 
318  // conversion
319  void convert(
320  const symbolt &class_symbol,
321  const methodt &,
322  const std::optional<prefix_filtert> &method_context);
323 
325  const methodt &method,
326  const java_method_typet &method_type);
327 
329 
330  codet get_clinit_call(const irep_idt &classname);
331 
332  bool is_method_inherited(
333  const irep_idt &classname,
334  const irep_idt &mangled_method_name) const;
335 
337  const irep_idt &class_identifier, const irep_idt &component_name) const;
338 
340  {
341  VARIABLE,
342  ARRAY_REF,
343  STATIC_FIELD,
344  FIELD
345  };
346 
347  void save_stack_entries(
348  const std::string &,
349  code_blockt &,
350  const bytecode_write_typet,
351  const irep_idt &);
352 
354  const std::string &,
355  const typet &,
356  code_blockt &,
357  exprt &);
358 
359  std::vector<method_offsett> try_catch_handler(
360  method_offsett address,
362  const;
363 
365  address_mapt &address_map,
366  const std::vector<method_offsett> &jsr_ret_targets,
367  const std::vector<
368  std::vector<java_bytecode_parse_treet::instructiont>::const_iterator>
369  &ret_instructions) const;
370 
371  std::optional<exprt> convert_invoke_dynamic(
372  const source_locationt &location,
373  std::size_t instruction_address,
374  const exprt &arg0,
375  codet &result_code);
376 
378  const irep_idt &statement,
379  const exprt::operandst &op,
380  const source_locationt &location);
381 
383  const irep_idt &statement,
384  const exprt &arg0,
385  const exprt::operandst &op,
386  const method_offsett address,
387  const source_locationt &location);
388 
389  static exprt
390  convert_aload(const irep_idt &statement, const exprt::operandst &op);
391 
401  exprt convert_load(const exprt &index, char type_char, size_t address);
402 
404  const std::vector<method_offsett> &jsr_ret_targets,
405  const exprt &arg0,
406  const source_locationt &location,
407  const method_offsett address);
408 
411  const u1 bytecode,
412  const exprt::operandst &op,
413  const mp_integer &number,
414  const source_locationt &location) const;
415 
418  const exprt::operandst &op,
419  const irep_idt &id,
420  const mp_integer &number,
421  const source_locationt &location) const;
422 
425  const exprt::operandst &op,
426  const mp_integer &number,
427  const source_locationt &location) const;
428 
431  const exprt::operandst &op,
432  const mp_integer &number,
433  const source_locationt &location) const;
434 
436  const exprt &arg0,
437  const exprt &arg1,
438  const source_locationt &location,
439  method_offsett address);
440 
442  const irep_idt &statement,
443  const exprt::operandst &op,
444  exprt::operandst &results) const;
445 
447  const irep_idt &statement,
448  const exprt::operandst &op,
449  exprt::operandst &results) const;
450 
452  convert_cmp(const exprt::operandst &op, exprt::operandst &results) const;
453 
455  const irep_idt &statement,
456  const exprt::operandst &op,
457  exprt::operandst &results) const;
458 
459  void convert_getstatic(
460  const source_locationt &source_location,
461  const exprt &arg0,
462  const symbol_exprt &symbol_expr,
463  bool is_assertions_disabled_field,
464  codet &c,
465  exprt::operandst &results);
466 
468  convert_putfield(const fieldref_exprt &arg0, const exprt::operandst &op);
469 
471  const source_locationt &location,
472  const exprt &arg0,
473  const exprt::operandst &op,
474  const symbol_exprt &symbol_expr);
475 
476  void convert_new(
477  const source_locationt &location,
478  const exprt &arg0,
479  codet &c,
480  exprt::operandst &results);
481 
483  const source_locationt &location,
484  const irep_idt &statement,
485  const exprt &arg0,
486  const exprt::operandst &op,
487  exprt::operandst &results);
488 
490  const source_locationt &location,
491  const exprt &arg0,
492  const exprt::operandst &op,
493  exprt::operandst &results);
494 
496  const methodt &method,
497  const std::set<method_offsett> &working_set,
498  method_offsett cur_pc,
499  codet &c);
500 
501  void convert_athrow(
502  const source_locationt &location,
503  const exprt::operandst &op,
504  codet &c,
505  exprt::operandst &results) const;
506 
507  void convert_checkcast(
508  const exprt &arg0,
509  const exprt::operandst &op,
510  codet &c,
511  exprt::operandst &results) const;
512 
514  const irep_idt &statement,
515  const exprt::operandst &op,
516  const source_locationt &source_location);
517 
519 
520  void convert_invoke(
521  source_locationt location,
522  const irep_idt &statement,
523  class_method_descriptor_exprt &class_method_descriptor,
524  codet &c,
525  exprt::operandst &results);
526 
528  const irep_idt &statement,
529  const constant_exprt &arg0,
530  exprt::operandst &results) const;
531 
533 
535 
536  void convert_dup2(exprt::operandst &op, exprt::operandst &results);
537 
539  const exprt::operandst &op,
541  const source_locationt &location);
542 
543  codet convert_pop(const irep_idt &statement, const exprt::operandst &op);
544 
546 };
547 #endif
uint8_t u1
Definition: bytecode_info.h:55
Compute dominators for CFG of goto_function.
Context-insensitive lazy methods container.
Non-graph-based representation of the class hierarchy.
An expression describing a method on a class.
Definition: std_expr.h:3503
A codet representing sequential composition of program statements.
Definition: std_code.h:130
codet representation of an if-then-else statement.
Definition: std_code.h:460
codet representing a switch statement.
Definition: std_code.h:548
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:29
A constant literal expression.
Definition: std_expr.h:2990
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
std::vector< exprt > operandst
Definition: expr.h:58
Represents the argument of an instruction that uses a CONSTANT_Fieldref This is used for example as a...
variablet(const symbol_exprt &_symbol_expr, std::size_t _start_pc, std::size_t _length, bool _is_parameter, std::vector< holet > &&_holes)
variablet(const symbol_exprt &_symbol_expr, std::size_t _start_pc, std::size_t _length, bool _is_parameter)
variablet(const symbol_exprt &_symbol_expr, std::size_t _start_pc, std::size_t _length)
void convert_dup2_x2(exprt::operandst &op, exprt::operandst &results)
method_offsett slots_for_parameters
Number of local variable slots used by the JVM to pass parameters upon invocation of the method under...
irep_idt get_static_field(const irep_idt &class_identifier, const irep_idt &component_name) const
Get static field identifier referred to by class_identifier.component_name Note this may be inherited...
void draw_edges_from_ret_to_jsr(address_mapt &address_map, const std::vector< method_offsett > &jsr_ret_targets, const std::vector< std::vector< java_bytecode_parse_treet::instructiont >::const_iterator > &ret_instructions) const
code_ifthenelset convert_if_cmp(const java_bytecode_convert_methodt::address_mapt &address_map, const u1 bytecode, const exprt::operandst &op, const mp_integer &number, const source_locationt &location) const
void create_stack_tmp_var(const std::string &, const typet &, code_blockt &, exprt &)
actually create a temporary variable to hold the value of a stack entry
std::optional< ci_lazy_methods_neededt > needed_lazy_methods
cfg_dominators_templatet< method_with_amapt, method_offsett, false > java_cfg_dominatorst
codet & do_exception_handling(const methodt &method, const std::set< method_offsett > &working_set, method_offsett cur_pc, codet &c)
exprt::operandst & convert_ushr(const irep_idt &statement, const exprt::operandst &op, exprt::operandst &results) const
exprt convert_load(const exprt &index, char type_char, size_t address)
Load reference from local variable.
void setup_local_variables(const methodt &m, const address_mapt &amap)
See find_initializers_for_slot above for more detail.
const variablet & find_variable_for_slot(size_t address, variablest &var_list)
See above.
void push(const exprt::operandst &o)
code_blockt convert_store(const irep_idt &statement, const exprt &arg0, const exprt::operandst &op, const method_offsett address, const source_locationt &location)
code_blockt convert_astore(const irep_idt &statement, const exprt::operandst &op, const source_locationt &location)
std::optional< exprt > convert_invoke_dynamic(const source_locationt &location, std::size_t instruction_address, const exprt &arg0, codet &result_code)
static irep_idt label(const irep_idt &address)
std::vector< method_offsett > try_catch_handler(method_offsett address, const java_bytecode_parse_treet::methodt::exception_tablet &exception_table) const
code_blockt convert_instructions(const methodt &)
codet & replace_call_to_cprover_assume(source_locationt location, codet &c)
java_string_library_preprocesst & string_preprocess
void convert(const symbolt &class_symbol, const methodt &, const std::optional< prefix_filtert > &method_context)
code_blockt convert_ret(const std::vector< method_offsett > &jsr_ret_targets, const exprt &arg0, const source_locationt &location, const method_offsett address)
void find_initializers(local_variable_table_with_holest &vars, const address_mapt &amap, const java_cfg_dominatorst &doms)
See find_initializers_for_slot above for more detail.
codet get_clinit_call(const irep_idt &classname)
Each static access to classname should be prefixed with a check for necessary static init; this retur...
code_blockt convert_putstatic(const source_locationt &location, const exprt &arg0, const exprt::operandst &op, const symbol_exprt &symbol_expr)
code_ifthenelset convert_if(const java_bytecode_convert_methodt::address_mapt &address_map, const exprt::operandst &op, const irep_idt &id, const mp_integer &number, const source_locationt &location) const
java_bytecode_parse_treet::methodt methodt
std::vector< local_variable_with_holest > local_variable_table_with_holest
code_ifthenelset convert_ifnull(const java_bytecode_convert_methodt::address_mapt &address_map, const exprt::operandst &op, const mp_integer &number, const source_locationt &location) const
code_blockt & get_block_for_pcrange(block_tree_nodet &tree, code_blockt &this_block, method_offsett address_start, method_offsett address_limit, method_offsett next_block_start_address)
'tree' describes a tree of code_blockt objects; this_block is the corresponding block (thus they are ...
void find_initializers_for_slot(local_variable_table_with_holest::iterator firstvar, local_variable_table_with_holest::iterator varlimit, const address_mapt &amap, const java_cfg_dominatorst &doms)
Given a sequence of users of the same local variable slot, this figures out which ones are related by...
codet convert_pop(const irep_idt &statement, const exprt::operandst &op)
exprt::operandst pop(std::size_t n)
java_bytecode_parse_treet::instructiont instructiont
exprt::operandst & convert_const(const irep_idt &statement, const constant_exprt &arg0, exprt::operandst &results) const
void convert_checkcast(const exprt &arg0, const exprt::operandst &op, codet &c, exprt::operandst &results) const
void convert_dup2_x1(exprt::operandst &op, exprt::operandst &results)
code_blockt convert_putfield(const fieldref_exprt &arg0, const exprt::operandst &op)
code_blockt convert_multianewarray(const source_locationt &location, const exprt &arg0, const exprt::operandst &op, exprt::operandst &results)
code_ifthenelset convert_ifnonull(const java_bytecode_convert_methodt::address_mapt &address_map, const exprt::operandst &op, const mp_integer &number, const source_locationt &location) const
void operator()(const symbolt &class_symbol, const methodt &method, const std::optional< prefix_filtert > &method_context)
code_blockt convert_parameter_annotations(const methodt &method, const java_method_typet &method_type)
code_switcht convert_switch(const exprt::operandst &op, const java_bytecode_parse_treet::instructiont::argst &args, const source_locationt &location)
void save_stack_entries(const std::string &, code_blockt &, const bytecode_write_typet, const irep_idt &)
Create temporary variables if a write instruction can have undesired side- effects.
bool is_parameter(const local_variablet &v)
Returns true iff the slot index of the local variable of a method (coming from the LVT) is a paramete...
void convert_new(const source_locationt &location, const exprt &arg0, codet &c, exprt::operandst &results)
exprt variable(const exprt &arg, char type_char, size_t address)
Returns an expression indicating a local variable suitable to load/store from a bytecode at address a...
std::map< method_offsett, converted_instructiont > address_mapt
methodt::local_variable_tablet local_variable_tablet
std::map< irep_idt, bool > any_superclass_has_clinit_method
static void replace_goto_target(codet &repl, const irep_idt &old_label, const irep_idt &new_label)
Find all goto statements in 'repl' that target 'old_label' and redirect them to 'new_label'.
code_blockt convert_iinc(const exprt &arg0, const exprt &arg1, const source_locationt &location, method_offsett address)
java_bytecode_convert_methodt(symbol_table_baset &symbol_table, message_handlert &_message_handler, size_t _max_array_length, bool throw_assertion_error, std::optional< ci_lazy_methods_neededt > needed_lazy_methods, java_string_library_preprocesst &_string_preprocess, const class_hierarchyt &class_hierarchy, bool threading_support, bool assert_no_exceptions_thrown)
exprt::operandst & convert_cmp2(const irep_idt &statement, const exprt::operandst &op, exprt::operandst &results) const
void convert_dup2(exprt::operandst &op, exprt::operandst &results)
bool is_method_inherited(const irep_idt &classname, const irep_idt &mangled_method_name) const
Returns true iff method methodid from class classname is a method inherited from a class or interface...
void convert_athrow(const source_locationt &location, const exprt::operandst &op, codet &c, exprt::operandst &results) const
typet method_return_type
Return type of the method under conversion.
void convert_getstatic(const source_locationt &source_location, const exprt &arg0, const symbol_exprt &symbol_expr, bool is_assertions_disabled_field, codet &c, exprt::operandst &results)
irep_idt method_id
Fully qualified name of the method under translation.
code_blockt convert_newarray(const source_locationt &location, const irep_idt &statement, const exprt &arg0, const exprt::operandst &op, exprt::operandst &results)
exprt::operandst & convert_shl(const irep_idt &statement, const exprt::operandst &op, exprt::operandst &results) const
exprt::operandst & convert_cmp(const exprt::operandst &op, exprt::operandst &results) const
void pop_residue(std::size_t n)
removes minimum(n, stack.size()) elements from the stack
void convert_invoke(source_locationt location, const irep_idt &statement, class_method_descriptor_exprt &class_method_descriptor, codet &c, exprt::operandst &results)
code_blockt & get_or_create_block_for_pcrange(block_tree_nodet &tree, code_blockt &this_block, method_offsett address_start, method_offsett address_limit, method_offsett next_block_start_address, const address_mapt &amap, bool allow_merge=true)
As above, but this version can additionally create a new branch in the block_tree-node and code_block...
codet convert_monitorenterexit(const irep_idt &statement, const exprt::operandst &op, const source_locationt &source_location)
irep_idt current_method
A copy of method_id :/.
static exprt convert_aload(const irep_idt &statement, const exprt::operandst &op)
symbol_exprt tmp_variable(const std::string &prefix, const typet &type)
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
Provides filtering of strings vai inclusion/exclusion lists of prefixes.
Definition: prefix_filter.h:20
Expression to hold a symbol (variable)
Definition: std_expr.h:131
The symbol table base class interface.
Symbol table entry.
Definition: symbol.h:28
The type of an expression, extends irept.
Definition: type.h:29
JAVA Bytecode Language Conversion.
java_bytecode_convert_methodt::address_mapt address_mapt
BigInt mp_integer
Definition: smt_terms.h:17
API to expression classes.
converted_instructiont(const instructionst::const_iterator &it, const codet &_code)
bool operator()(const method_offsett &a, const method_offsett &b) const
std::pair< const methodt &, const address_mapt & > method_with_amap
std::vector< local_variablet > local_variable_tablet
std::vector< instructiont > instructionst