void java_bytecode_convert_classt::convert( symbolt &class_symbol, const fieldt &f) { typet field_type=java_type_from_string(f.signature); // is this a static field? if(f.is_static) { // Create the symbol; we won't add to the struct type. symbolt new_symbol; new_symbol.is_static_lifetime=true; new_symbol.is_lvalue=true; new_symbol.is_state_var=true; new_symbol.name=id2string(class_symbol.name)+"."+id2string(f.name); new_symbol.base_name=f.name; new_symbol.type=field_type; new_symbol.pretty_name=id2string(class_symbol.pretty_name)+ "."+id2string(f.name); new_symbol.mode=ID_java; new_symbol.is_type=false; const namespacet ns(symbol_table); new_symbol.value= zero_initializer( field_type, class_symbol.location, ns, get_message_handler()); // Do we have the static field symbol already? const auto s_it=symbol_table.symbols.find(new_symbol.name); if(s_it!=symbol_table.symbols.end()) symbol_table.symbols.erase(s_it); // erase, we stubbed it if(symbol_table.add(new_symbol)) assert(false && "failed to add static field symbol"); } else { class_typet &class_type=to_class_type(class_symbol.type); class_type.components().push_back(class_typet::componentt()); class_typet::componentt &component=class_type.components().back(); component.set_name(f.name); component.set_base_name(f.name); component.set_pretty_name(f.name); component.type()=field_type; if(f.is_private) component.set_access(ID_private); else if(f.is_protected) component.set_access(ID_protected); else if(f.is_public) component.set_access(ID_public); } }
void java_bytecode_parsert::get_class_refs() { // Get the class references for the benefit of a dependency // analysis. for(const auto &c : constant_pool) { switch(c.tag) { case CONSTANT_Class: get_class_refs_rec(c.expr.type()); break; case CONSTANT_NameAndType: { typet t=java_type_from_string(id2string(pool_entry(c.ref2).s)); get_class_refs_rec(t); } break; default: {} } } for(const auto &m : parse_tree.parsed_class.fields) { typet t=java_type_from_string(m.signature); get_class_refs_rec(t); } for(const auto &m : parse_tree.parsed_class.methods) { typet t=java_type_from_string(m.signature); get_class_refs_rec(t); for(const auto &var : m.local_variable_table) { typet var_type=java_type_from_string(var.signature); get_class_refs_rec(var_type); } } }
void java_bytecode_convertt::convert( symbolt &class_symbol, const fieldt &f) { class_typet &class_type=to_class_type(class_symbol.type); typet member_type=java_type_from_string(f.signature); class_type.components().push_back(class_typet::componentt()); class_typet::componentt &component=class_type.components().back(); component.set_name(f.name); component.set_base_name(f.name); component.set_pretty_name(f.name); component.type()=member_type; if(f.is_private) component.set_access(ID_private); else if(f.is_protected) component.set_access(ID_protected); else if(f.is_public) component.set_access(ID_public); // is this a static field? if(f.is_static) { // create the symbol symbolt new_symbol; new_symbol.is_static_lifetime=true; new_symbol.is_lvalue=true; new_symbol.is_state_var=true; new_symbol.name=id2string(class_symbol.name)+"."+id2string(f.name); new_symbol.base_name=f.name; new_symbol.type=member_type; new_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+id2string(f.name); new_symbol.mode=ID_java; new_symbol.is_type=false; new_symbol.value=gen_zero(member_type); if(symbol_table.add(new_symbol)) { error() << "failed to add static field symbol" << eom; throw 0; } } }
void java_bytecode_convertt::convert( symbolt &class_symbol, const methodt &m) { class_typet &class_type=to_class_type(class_symbol.type); typet member_type=java_type_from_string(m.signature); assert(member_type.id()==ID_code); const irep_idt method_identifier= id2string(class_symbol.name)+"."+id2string(m.name)+":"+m.signature; code_typet &code_type=to_code_type(member_type); method_return_type=code_type.return_type(); code_typet::parameterst ¶meters=code_type.parameters(); // do we need to add 'this' as a parameter? if(!m.is_static) { code_typet::parametert this_p; const empty_typet empty; const pointer_typet object_ref_type(empty); this_p.type()=object_ref_type; this_p.set_this(); parameters.insert(parameters.begin(), this_p); } variables.clear(); // Do the parameters and locals in the variable table, // which is only available when compiled with -g for(const auto & v : m.local_variable_table) { typet t=java_type_from_string(v.signature); irep_idt identifier=id2string(method_identifier)+"::"+id2string(v.name); symbol_exprt result(identifier, t); result.set(ID_C_base_name, v.name); variables[v.index].symbol_expr=result; } // set up variables array for(std::size_t i=0, param_index=0; i < parameters.size(); ++i) { variables[param_index]; param_index+=get_variable_slots(parameters[i]); } // assign names to parameters for(std::size_t i=0, param_index=0; i < parameters.size(); ++i) { irep_idt base_name, identifier; if(i==0 && parameters[i].get_this()) { base_name="this"; identifier=id2string(method_identifier)+"::"+id2string(base_name); parameters[i].set_base_name(base_name); parameters[i].set_identifier(identifier); } else { // in the variable table? base_name=variables[param_index].symbol_expr.get(ID_C_base_name); identifier=variables[param_index].symbol_expr.get(ID_identifier); if(base_name.empty()) { const typet &type=parameters[i].type(); char suffix=java_char_from_type(type); base_name="arg"+i2string(param_index)+suffix; identifier=id2string(method_identifier)+"::"+id2string(base_name); } parameters[i].set_base_name(base_name); parameters[i].set_identifier(identifier); } // add to symbol table parameter_symbolt parameter_symbol; parameter_symbol.base_name=base_name; parameter_symbol.mode=ID_java; parameter_symbol.name=identifier; parameter_symbol.type=parameters[i].type(); symbol_table.add(parameter_symbol); // add as a JVM variable unsigned slots=get_variable_slots(parameters[i]); variables[param_index].symbol_expr=parameter_symbol.symbol_expr(); param_index+=slots; } class_type.methods().push_back(class_typet::methodt()); class_typet::methodt &method=class_type.methods().back(); method.set_base_name(m.base_name); method.set_name(method_identifier); const bool is_virtual=!m.is_static && !m.is_final; method.set(ID_abstract, m.is_abstract); method.set(ID_is_virtual, is_virtual); if(is_contructor(method)) method.set(ID_constructor, true); method.type()=member_type; // we add the symbol for the method symbolt method_symbol; method_symbol.name=method.get_name(); method_symbol.base_name=method.get_base_name(); method_symbol.mode=ID_java; method_symbol.name=method.get_name(); method_symbol.base_name=method.get_base_name(); if(method.get_base_name()=="<init>") method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ id2string(class_symbol.base_name)+"()"; else method_symbol.pretty_name=id2string(class_symbol.pretty_name)+"."+ id2string(method.get_base_name())+"()"; method_symbol.type=member_type; current_method=method_symbol.name; method_has_this=code_type.has_this(); tmp_vars.clear(); method_symbol.value=convert_instructions(m.instructions, code_type); // do we have the method symbol already? const auto s_it=symbol_table.symbols.find(method.get_name()); if(s_it!=symbol_table.symbols.end()) symbol_table.symbols.erase(s_it); // erase, we stubbed it symbol_table.add(method_symbol); }
typet java_type_from_string(const std::string &src) { if(src.empty()) return nil_typet(); switch(src[0]) { case '(': // function type { std::size_t e_pos=src.rfind(')'); if(e_pos==std::string::npos) return nil_typet(); code_typet result; result.return_type()= java_type_from_string(std::string(src, e_pos+1, std::string::npos)); for(std::size_t i=1; i<src.size() && src[i]!=')'; i++) { code_typet::parametert param; size_t start=i; while(i<src.size()) { if(src[i]=='L') { i=src.find(';', i); // ends on ; break; } else if(src[i]=='[') i++; else break; } std::string sub_str=src.substr(start, i-start+1); param.type()=java_type_from_string(sub_str); if(param.type().id()==ID_symbol) param.type()=java_reference_type(param.type()); result.parameters().push_back(param); } return result; } case '[': // array type { if(src.size()<=2) return nil_typet(); typet subtype=java_type_from_string(src.substr(1, std::string::npos)); return java_reference_type(java_array_type(subtype)); } case 'F': return java_float_type(); case 'D': return java_double_type(); case 'I': return java_int_type(); case 'C': return java_char_type(); case 'Z': return java_boolean_type(); case 'V': return java_void_type(); case 'J': return java_long_type(); case 'L': { // ends on ; if(src[src.size()-1]!=';') return nil_typet(); std::string identifier="java::"+src.substr(1, src.size()-2); for(unsigned i=0; i<identifier.size(); i++) if(identifier[i]=='/') identifier[i]='.'; reference_typet result; result.subtype()=symbol_typet(identifier); return result; } default: return nil_typet(); } }
const typet type_entry(u2 index) { return java_type_from_string(id2string(pool_entry(index).s)); }
exprt::operandst java_build_arguments( const symbolt &function, code_blockt &init_code, symbol_tablet &symbol_table, bool assume_init_pointers_not_null, unsigned max_nondet_array_length, message_handlert &message_handler) { const code_typet::parameterst ¶meters= to_code_type(function.type).parameters(); exprt::operandst main_arguments; main_arguments.resize(parameters.size()); for(std::size_t param_number=0; param_number<parameters.size(); param_number++) { bool is_this=(param_number==0) && parameters[param_number].get_this(); bool is_default_entry_point(config.main.empty()); bool is_main=is_default_entry_point; if(!is_main) { bool named_main=has_suffix(config.main, ".main"); const typet &string_array_type= java_type_from_string("[Ljava.lang.String;"); bool has_correct_type= to_code_type(function.type).return_type().id()==ID_empty && (!to_code_type(function.type).has_this()) && parameters.size()==1 && parameters[0].type().full_eq(string_array_type); is_main=(named_main && has_correct_type); } bool allow_null=(!is_main) && (!is_this) && !assume_init_pointers_not_null; main_arguments[param_number]= object_factory( parameters[param_number].type(), init_code, allow_null, symbol_table, max_nondet_array_length, function.location, message_handler); const symbolt &p_symbol= symbol_table.lookup(parameters[param_number].get_identifier()); // record as an input codet input(ID_input); input.operands().resize(2); input.op0()= address_of_exprt( index_exprt( string_constantt(p_symbol.base_name), from_integer(0, index_type()))); input.op1()=main_arguments[param_number]; input.add_source_location()=function.location; init_code.move_to_operands(input); } return main_arguments; }