bool type_eq(const typet &type1, const typet &type2, const namespacet &ns) { if(type1 == type2) return true; if(type1.id() == "symbol") { const symbolt &symbol = ns.lookup(type1); if(!symbol.is_type) throw "symbol " + id2string(symbol.name) + " is not a type"; return type_eq(symbol.type, type2, ns); } if(type2.id() == "symbol") { const symbolt &symbol = ns.lookup(type2); if(!symbol.is_type) throw "symbol " + id2string(symbol.name) + " is not a type"; return type_eq(type1, symbol.type, ns); } return false; }
std::string array_name( const namespacet &ns, const exprt &expr) { if(expr.id()==ID_index) { if(expr.operands().size()!=2) throw "index takes two operands"; return array_name(ns, expr.op0())+"[]"; } else if(is_ssa_expr(expr)) { const symbolt &symbol= ns.lookup(to_ssa_expr(expr).get_object_name()); return "array `"+id2string(symbol.base_name)+"'"; } else if(expr.id()==ID_symbol) { const symbolt &symbol=ns.lookup(expr); return "array `"+id2string(symbol.base_name)+"'"; } else if(expr.id()==ID_string_constant) { return "string constant"; } else if(expr.id()==ID_member) { assert(expr.operands().size()==1); return array_name(ns, expr.op0())+"."+ expr.get_string(ID_component_name); } return "array"; }
exprt get_failed_symbol( const symbol_exprt &expr, const namespacet &ns) { const symbolt &symbol=ns.lookup(expr); irep_idt failed_symbol_id=symbol.type.get("#failed_symbol"); if(failed_symbol_id==irep_idt()) return nil_exprt(); const symbolt &failed_symbol=ns.lookup(failed_symbol_id); return symbol_exprt(failed_symbol_id, failed_symbol.type); }
void uninitialized_domaint::transform( locationt from, locationt to, ai_baset &ai, const namespacet &ns) { if(has_values.is_false()) return; switch(from->type) { case DECL: { const irep_idt &identifier= to_code_decl(from->code).get_identifier(); const symbolt &symbol=ns.lookup(identifier); if(!symbol.is_static_lifetime) uninitialized.insert(identifier); } break; default: { std::list<exprt> read=expressions_read(*from); std::list<exprt> written=expressions_written(*from); forall_expr_list(it, written) assign(*it); // we only care about the *first* uninitalized use forall_expr_list(it, read) assign(*it); } } }
std::unique_ptr<languaget> get_language( const namespacet &ns, const irep_idt &identifier) { if(identifier=="") return std::unique_ptr<languaget>(get_default_language()); else { const symbolt *symbol; if(ns.lookup(identifier, symbol)) return std::unique_ptr<languaget>(get_default_language()); else if(symbol->mode=="") return std::unique_ptr<languaget>(get_default_language()); else { languaget *ptr=get_language_from_mode(symbol->mode); if(ptr==NULL) throw "symbol `"+id2string(symbol->name)+ "' has unknown mode '"+id2string(symbol->mode)+"'"; return std::unique_ptr<languaget>(ptr); } } }
void base_type_rec( typet &type, const namespacet &ns, std::set<irep_idt> &symb) { if(type.id()==ID_symbol || type.id()==ID_c_enum_tag || type.id()==ID_struct_tag || type.id()==ID_union_tag) { const symbolt *symbol; if(!ns.lookup(type.get(ID_identifier), symbol) && symbol->is_type && !symbol->type.is_nil()) { type=symbol->type; base_type_rec(type, ns, symb); // recursive call return; } } else if(type.id()==ID_array) { base_type_rec(to_array_type(type).subtype(), ns, symb); } else if(type.id()==ID_struct || type.id()==ID_union) { struct_union_typet::componentst &components= to_struct_union_type(type).components(); for(auto &component : components) base_type_rec(component.type(), ns, symb); } else if(type.id()==ID_pointer) { typet &subtype=to_pointer_type(type).subtype(); // we need to avoid running into an infinite loop if(subtype.id()==ID_symbol || subtype.id()==ID_c_enum_tag || subtype.id()==ID_struct_tag || subtype.id()==ID_union_tag) { const irep_idt &id=subtype.get(ID_identifier); if(symb.find(id)!=symb.end()) return; symb.insert(id); base_type_rec(subtype, ns, symb); symb.erase(id); } else base_type_rec(subtype, ns, symb); } }
/// automated variable renaming /// \par parameters: symbol to be renamed, namespace /// \return new symbol void get_new_name(irep_idt &new_name, const namespacet &ns) { const symbolt *symbol; if(ns.lookup(new_name, symbol)) return; std::string prefix=id2string(new_name)+"_"; new_name=prefix+std::to_string(ns.get_max(prefix)+1); }
void get_symbols_rec( const namespacet &ns, const symbolt &symbol, find_symbols_sett &dest) { dest.insert(symbol.name); find_symbols_sett new_symbols; find_type_and_expr_symbols(symbol.type, new_symbols); find_type_and_expr_symbols(symbol.value, new_symbols); if(symbol.type.id()==ID_code) { const code_typet &code_type=to_code_type(symbol.type); const code_typet::parameterst ¶meters=code_type.parameters(); for(code_typet::parameterst::const_iterator it=parameters.begin(); it!=parameters.end(); it++) { irep_idt id=it->get_identifier(); const symbolt *s; // identifiers for prototypes need not exist if(!ns.lookup(id, s)) new_symbols.insert(id); } } for(find_symbols_sett::const_iterator it=new_symbols.begin(); it!=new_symbols.end(); it++) { if(dest.find(*it)==dest.end()) { dest.insert(*it); get_symbols_rec(ns, ns.lookup(*it), dest); // recursive call } } }
exprt remove_virtual_functionst::get_method( const irep_idt &class_id, const irep_idt &component_name) const { irep_idt id=id2string(class_id)+"."+ id2string(component_name); const symbolt *symbol; if(ns.lookup(id, symbol)) return nil_exprt(); return symbol->symbol_expr(); }
static std::string type2name_symbol( const typet &type, const namespacet &ns, symbol_numbert &symbol_number) { const irep_idt &identifier=type.get(ID_identifier); const symbolt *symbol; if(ns.lookup(identifier, symbol)) return "SYM#"+id2string(identifier)+"#"; assert(symbol && symbol->is_type); if(symbol->type.id()!=ID_struct && symbol->type.id()!=ID_union) return type2name(symbol->type, ns, symbol_number); std::string result; // assign each symbol a number when seen for the first time std::pair<symbol_numbert::iterator, bool> entry= symbol_number.insert(std::make_pair( identifier, std::make_pair(symbol_number.size(), true))); // new entry, add definition if(entry.second) { result="SYM#"+std::to_string(entry.first->second.first); result+="={"; result+=type2name(symbol->type, ns, symbol_number); result+='}'; entry.first->second.second=false; } #if 0 // in recursion, print the shorthand only else if(entry.first->second.second) result="SYM#"+std::to_string(entry.first->second.first); // entering recursion else { entry.first->second.second=true; result=type2name(symbol->type, ns, symbol_number); entry.first->second.second=false; } #else // shorthand only as structs/unions are always symbols else
void nondet_static( const namespacet &ns, goto_functionst &goto_functions, const irep_idt &fct_name) { goto_functionst::function_mapt::iterator i_it=goto_functions.function_map.find(fct_name); assert(i_it!=goto_functions.function_map.end()); goto_programt &init=i_it->second.body; Forall_goto_program_instructions(i_it, init) { const goto_programt::instructiont &instruction=*i_it; if(instruction.is_assign()) { const symbol_exprt &sym=to_symbol_expr( to_code_assign(instruction.code).lhs()); // is it a __CPROVER_* variable? if(has_prefix(id2string(sym.get_identifier()), CPROVER_PREFIX)) continue; // static lifetime? if(!ns.lookup(sym.get_identifier()).is_static_lifetime) continue; // constant? if(sym.type().get_bool(ID_C_constant)) continue; i_it=init.insert_before(++i_it); i_it->make_assignment(); i_it->code=code_assignt(sym, side_effect_expr_nondett(sym.type())); i_it->location=instruction.location; i_it->function=instruction.function; } else if(instruction.is_function_call()) { const code_function_callt &fct=to_code_function_call(instruction.code); const symbol_exprt &fsym=to_symbol_expr(fct.function()); if(has_prefix(id2string(fsym.get_identifier()), "c::#ini#")) nondet_static(ns, goto_functions, fsym.get_identifier()); } } }
exprt to_expr( const namespacet &ns, const irep_idt &identifier, const std::string &src) { std::unique_ptr<languaget> p=get_language(ns, identifier); const symbolt &symbol=ns.lookup(identifier); exprt expr; if(p->to_expr(src, id2string(symbol.module), expr, ns)) return nil_exprt(); return expr; }
int configt::ansi_ct::from_ns(const namespacet &ns, const std::string &what) { const irep_idt id="c::__CPROVER_architecture_"+what; const symbolt *symbol; if(ns.lookup(id, symbol)) throw "failed to find "+id2string(id); exprt tmp=symbol->value; simplify(tmp, ns); mp_integer int_value; if(to_integer(tmp, int_value)) throw "failed to convert "+id2string(id); return integer2long(int_value); }
void predicatest::make_expr_passive_rec( exprt& phi, const namespacet& ns, const unsigned subscript) { Forall_operands(it, phi) make_expr_passive_rec(*it, ns, subscript); if(phi.id()==ID_symbol) { symbol_exprt &phi_sym=to_symbol_expr(phi); const irep_idt &identifier=phi_sym.get_identifier(); assert(identifier.as_string().find('#')==std::string::npos); if(is_procedure_local(ns.lookup(identifier))) { std::ostringstream os; os << identifier << '#' << subscript; phi_sym.set_identifier(os.str()); } } }
static unsigned from_ns( const namespacet &ns, const std::string &what) { const irep_idt id=CPROVER_PREFIX "architecture_"+what; const symbolt *symbol; if(ns.lookup(id, symbol)) throw "failed to find "+id2string(id); exprt tmp=symbol->value; simplify(tmp, ns); if(tmp.id()!=ID_constant) throw "symbol table configuration entry `"+id2string(id)+"' is not a constant"; mp_integer int_value; if(to_integer(to_constant_expr(tmp), int_value)) throw "failed to convert symbol table configuration entry `"+id2string(id)+"'"; return integer2unsigned(int_value); }
static irep_idt string_from_ns( const namespacet &ns, const std::string &what) { const irep_idt id=CPROVER_PREFIX "architecture_"+what; const symbolt *symbol; if(ns.lookup(id, symbol)) throw "failed to find "+id2string(id); const exprt &tmp=symbol->value; if(tmp.id()!=ID_address_of || tmp.operands().size()!=1 || tmp.op0().id()!=ID_index || tmp.op0().operands().size()!=2 || tmp.op0().op0().id()!=ID_string_constant) { throw "symbol table configuration entry `"+id2string(id)+"' is not a string constant"; } return tmp.op0().op0().get(ID_value); }
void find_macros( const exprt &src, const namespacet &ns, find_macros_sett &dest) { std::stack<const exprt *> stack; // use stack, these may be nested deeply stack.push(&src); while(!stack.empty()) { const exprt &e=*stack.top(); stack.pop(); if(e.id()==ID_symbol || e.id()==ID_next_symbol) { const irep_idt &identifier=e.get(ID_identifier); const symbolt &symbol=ns.lookup(identifier); if(symbol.is_macro) { // inserted? if(dest.insert(identifier).second) stack.push(&symbol.value); } } else { forall_operands(it, e) stack.push(&(*it)); } } }
void string_instrumentationt::do_strerror( goto_programt &dest, goto_programt::targett it, code_function_callt &call) { if(call.lhs().is_nil()) { it->make_skip(); return; } irep_idt identifier_buf="c::__strerror_buffer"; irep_idt identifier_size="c::__strerror_buffer_size"; if(context.symbols.find(identifier_buf)==context.symbols.end()) { symbolt new_symbol_size; new_symbol_size.base_name="__strerror_buffer_size"; new_symbol_size.pretty_name=new_symbol_size.base_name; new_symbol_size.name=identifier_size; new_symbol_size.mode="C"; new_symbol_size.type=uint_type(); new_symbol_size.is_statevar=true; new_symbol_size.lvalue=true; new_symbol_size.static_lifetime=true; array_typet type; type.subtype()=char_type(); type.size()=symbol_expr(new_symbol_size); symbolt new_symbol_buf; new_symbol_buf.mode="C"; new_symbol_buf.type=type; new_symbol_buf.is_statevar=true; new_symbol_buf.lvalue=true; new_symbol_buf.static_lifetime=true; new_symbol_buf.base_name="__strerror_buffer"; new_symbol_buf.pretty_name=new_symbol_buf.base_name; new_symbol_buf.name="c::"+id2string(new_symbol_buf.base_name); context.move(new_symbol_buf); context.move(new_symbol_size); } const symbolt &symbol_size=ns.lookup(identifier_size); const symbolt &symbol_buf=ns.lookup(identifier_buf); goto_programt tmp; { goto_programt::targett assignment1=tmp.add_instruction(ASSIGN); exprt nondet_size=side_effect_expr_nondett(uint_type()); assignment1->code=code_assignt(symbol_expr(symbol_size), nondet_size); assignment1->location=it->location; goto_programt::targett assumption1=tmp.add_instruction(); assumption1->make_assumption(binary_relation_exprt( symbol_expr(symbol_size), "notequal", gen_zero(symbol_size.type))); assumption1->location=it->location; } // return a pointer to some magic buffer exprt index=exprt("index", char_type()); index.copy_to_operands(symbol_expr(symbol_buf), gen_zero(uint_type())); exprt ptr=exprt("address_of", pointer_typet()); ptr.type().subtype()=char_type(); ptr.copy_to_operands(index); // make that zero-terminated { goto_programt::targett assignment2=tmp.add_instruction(ASSIGN); assignment2->code=code_assignt(is_zero_string(ptr, true), true_exprt()); assignment2->location=it->location; } // assign address { goto_programt::targett assignment3=tmp.add_instruction(ASSIGN); exprt rhs=ptr; make_type(rhs, call.lhs().type()); assignment3->code=code_assignt(call.lhs(), rhs); assignment3->location=it->location; } it->make_skip(); dest.insert_before_swap(it, tmp); }
void string_instrumentationt::do_strerror( goto_programt &dest, goto_programt::targett it, code_function_callt &call) { if(call.lhs().is_nil()) { it->make_skip(); return; } irep_idt identifier_buf="__strerror_buffer"; irep_idt identifier_size="__strerror_buffer_size"; if(symbol_table.symbols.find(identifier_buf)==symbol_table.symbols.end()) { symbolt new_symbol_size; new_symbol_size.base_name="__strerror_buffer_size"; new_symbol_size.pretty_name=new_symbol_size.base_name; new_symbol_size.name=identifier_size; new_symbol_size.mode=ID_C; new_symbol_size.type=size_type(); new_symbol_size.is_state_var=true; new_symbol_size.is_lvalue=true; new_symbol_size.is_static_lifetime=true; array_typet type; type.subtype()=char_type(); type.size()=new_symbol_size.symbol_expr(); symbolt new_symbol_buf; new_symbol_buf.mode=ID_C; new_symbol_buf.type=type; new_symbol_buf.is_state_var=true; new_symbol_buf.is_lvalue=true; new_symbol_buf.is_static_lifetime=true; new_symbol_buf.base_name="__strerror_buffer"; new_symbol_buf.pretty_name=new_symbol_buf.base_name; new_symbol_buf.name=new_symbol_buf.base_name; symbol_table.move(new_symbol_buf); symbol_table.move(new_symbol_size); } const symbolt &symbol_size=ns.lookup(identifier_size); const symbolt &symbol_buf=ns.lookup(identifier_buf); goto_programt tmp; { goto_programt::targett assignment1=tmp.add_instruction(ASSIGN); exprt nondet_size=side_effect_expr_nondett(size_type()); assignment1->code=code_assignt(symbol_size.symbol_expr(), nondet_size); assignment1->source_location=it->source_location; goto_programt::targett assumption1=tmp.add_instruction(); assumption1->make_assumption( binary_relation_exprt( symbol_size.symbol_expr(), ID_notequal, from_integer(0, symbol_size.type))); assumption1->source_location=it->source_location; } // return a pointer to some magic buffer index_exprt index( symbol_buf.symbol_expr(), from_integer(0, index_type()), char_type()); address_of_exprt ptr(index); // make that zero-terminated { goto_programt::targett assignment2=tmp.add_instruction(ASSIGN); assignment2->code=code_assignt(is_zero_string(ptr, true), true_exprt()); assignment2->source_location=it->source_location; } // assign address { goto_programt::targett assignment3=tmp.add_instruction(ASSIGN); exprt rhs=ptr; make_type(rhs, call.lhs().type()); assignment3->code=code_assignt(call.lhs(), rhs); assignment3->source_location=it->source_location; } it->make_skip(); dest.insert_before_swap(it, tmp); }
void convert( const namespacet &ns, const goto_tracet &goto_trace, xmlt &dest) { dest=xmlt("goto_trace"); source_locationt previous_source_location; for(const auto & it : goto_trace.steps) { const source_locationt &source_location=it.pc->source_location; xmlt xml_location; if(source_location.is_not_nil() && source_location.get_file()!="") xml_location=xml(source_location); switch(it.type) { case goto_trace_stept::ASSERT: if(!it.cond_value) { irep_idt property_id; if(it.pc->is_assert()) property_id=source_location.get_property_id(); else if(it.pc->is_goto()) // unwinding, we suspect { property_id= id2string(it.pc->source_location.get_function())+".unwind."+ i2string(it.pc->loop_number); } xmlt &xml_failure=dest.new_element("failure"); xml_failure.set_attribute_bool("hidden", it.hidden); xml_failure.set_attribute("thread", i2string(it.thread_nr)); xml_failure.set_attribute("step_nr", i2string(it.step_nr)); xml_failure.set_attribute("reason", id2string(it.comment)); xml_failure.set_attribute("property", id2string(property_id)); if(xml_location.name!="") xml_failure.new_element().swap(xml_location); } break; case goto_trace_stept::ASSIGNMENT: case goto_trace_stept::DECL: { irep_idt identifier=it.lhs_object.get_identifier(); xmlt &xml_assignment=dest.new_element("assignment"); if(xml_location.name!="") xml_assignment.new_element().swap(xml_location); std::string value_string, binary_string, type_string, full_lhs_string, full_lhs_value_string; if(it.lhs_object_value.is_not_nil()) value_string=from_expr(ns, identifier, it.lhs_object_value); if(it.full_lhs.is_not_nil()) full_lhs_string=from_expr(ns, identifier, it.full_lhs); if(it.full_lhs_value.is_not_nil()) full_lhs_value_string=from_expr(ns, identifier, it.full_lhs_value); if(it.lhs_object_value.type().is_not_nil()) type_string=from_type(ns, identifier, it.lhs_object_value.type()); const symbolt *symbol; irep_idt base_name, display_name; if(!ns.lookup(identifier, symbol)) { base_name=symbol->base_name; display_name=symbol->display_name(); if(type_string=="") type_string=from_type(ns, identifier, symbol->type); xml_assignment.set_attribute("mode", id2string(symbol->mode)); } xml_assignment.new_element("type").data=type_string; xml_assignment.new_element("full_lhs").data=full_lhs_string; xml_assignment.new_element("full_lhs_value").data=full_lhs_value_string; xml_assignment.new_element("value").data=value_string; xml_assignment.set_attribute_bool("hidden", it.hidden); xml_assignment.set_attribute("thread", i2string(it.thread_nr)); xml_assignment.set_attribute("identifier", id2string(identifier)); xml_assignment.set_attribute("base_name", id2string(base_name)); xml_assignment.set_attribute("display_name", id2string(display_name)); xml_assignment.set_attribute("step_nr", i2string(it.step_nr)); xml_assignment.set_attribute("assignment_type", it.assignment_type==goto_trace_stept::ACTUAL_PARAMETER?"actual_parameter": "state"); if(it.lhs_object_value.is_not_nil()) xml_assignment.new_element("value_expression").new_element(xml(it.lhs_object_value, ns)); } break; case goto_trace_stept::OUTPUT: { printf_formattert printf_formatter(ns); printf_formatter(id2string(it.format_string), it.io_args); std::string text=printf_formatter.as_string(); xmlt &xml_output=dest.new_element("output"); xml_output.new_element("text").data=text; xml_output.set_attribute_bool("hidden", it.hidden); xml_output.set_attribute("thread", i2string(it.thread_nr)); xml_output.set_attribute("step_nr", i2string(it.step_nr)); if(xml_location.name!="") xml_output.new_element().swap(xml_location); for(const auto l_it : it.io_args) { xml_output.new_element("value").data=from_expr(ns, "", l_it); xml_output.new_element("value_expression"). new_element(xml(l_it, ns)); } } break; case goto_trace_stept::INPUT: { xmlt &xml_input=dest.new_element("input"); xml_input.new_element("input_id").data=id2string(it.io_id); xml_input.set_attribute_bool("hidden", it.hidden); xml_input.set_attribute("thread", i2string(it.thread_nr)); xml_input.set_attribute("step_nr", i2string(it.step_nr)); for(const auto & l_it : it.io_args) { xml_input.new_element("value").data=from_expr(ns, "", l_it); xml_input.new_element("value_expression"). new_element(xml(l_it, ns)); } if(xml_location.name!="") xml_input.new_element().swap(xml_location); } break; case goto_trace_stept::FUNCTION_CALL: case goto_trace_stept::FUNCTION_RETURN: { std::string tag= (it.type==goto_trace_stept::FUNCTION_CALL)?"function_call":"function_return"; xmlt &xml_call_return=dest.new_element(tag); xml_call_return.set_attribute_bool("hidden", it.hidden); xml_call_return.set_attribute("thread", i2string(it.thread_nr)); xml_call_return.set_attribute("step_nr", i2string(it.step_nr)); const symbolt &symbol=ns.lookup(it.identifier); xmlt &xml_function=xml_call_return.new_element("function"); xml_function.set_attribute("display_name", id2string(symbol.display_name())); xml_function.set_attribute("identifier", id2string(it.identifier)); xml_function.new_element()=xml(symbol.location); if(xml_location.name!="") xml_call_return.new_element().swap(xml_location); } break; default: if(source_location!=previous_source_location) { // just the source location if(xml_location.name!="") { xmlt &xml_location_only=dest.new_element("location-only"); xml_location_only.set_attribute_bool("hidden", it.hidden); xml_location_only.set_attribute("thread", i2string(it.thread_nr)); xml_location_only.set_attribute("step_nr", i2string(it.step_nr)); xml_location_only.new_element().swap(xml_location); } } } if(source_location.is_not_nil() && source_location.get_file()!="") previous_source_location=source_location; } }
void show_symbol_table_plain( const goto_modelt &goto_model, std::ostream &out) { out << '\n' << "Symbols:" << '\n' << '\n'; // we want to sort alphabetically std::set<std::string> symbols; forall_symbols(it, goto_model.symbol_table.symbols) symbols.insert(id2string(it->first)); const namespacet ns(goto_model.symbol_table); for(const std::string &id : symbols) { const symbolt &symbol=ns.lookup(id); languaget *ptr; if(symbol.mode=="") ptr=get_default_language(); else { ptr=get_language_from_mode(symbol.mode); if(ptr==NULL) throw "symbol "+id2string(symbol.name)+" has unknown mode"; } std::unique_ptr<languaget> p(ptr); std::string type_str, value_str; if(symbol.type.is_not_nil()) p->from_type(symbol.type, type_str, ns); if(symbol.value.is_not_nil()) p->from_expr(symbol.value, value_str, ns); out << "Symbol......: " << symbol.name << '\n' << std::flush; out << "Pretty name.: " << symbol.pretty_name << '\n'; out << "Module......: " << symbol.module << '\n'; out << "Base name...: " << symbol.base_name << '\n'; out << "Mode........: " << symbol.mode << '\n'; out << "Type........: " << type_str << '\n'; out << "Value.......: " << value_str << '\n'; out << "Flags.......:"; if(symbol.is_lvalue) out << " lvalue"; if(symbol.is_static_lifetime) out << " static_lifetime"; if(symbol.is_thread_local) out << " thread_local"; if(symbol.is_file_local) out << " file_local"; if(symbol.is_type) out << " type"; if(symbol.is_extern) out << " extern"; if(symbol.is_input) out << " input"; if(symbol.is_output) out << " output"; if(symbol.is_macro) out << " macro"; if(symbol.is_parameter) out << " parameter"; if(symbol.is_auxiliary) out << " auxiliary"; if(symbol.is_weak) out << " weak"; if(symbol.is_property) out << " property"; if(symbol.is_state_var) out << " state_var"; if(symbol.is_exported) out << " exported"; if(symbol.is_volatile) out << " volatile"; out << '\n'; out << "Location....: " << symbol.location << '\n'; out << '\n' << std::flush; } }
void convert( const namespacet &ns, const goto_tracet &goto_trace, jsont &dest) { json_arrayt &dest_array=dest.make_array(); source_locationt previous_source_location; for(const auto &step : goto_trace.steps) { const source_locationt &source_location=step.pc->source_location; jsont json_location; if(source_location.is_not_nil() && source_location.get_file()!="") json_location=json(source_location); else json_location=json_nullt(); switch(step.type) { case goto_trace_stept::typet::ASSERT: if(!step.cond_value) { irep_idt property_id; if(step.pc->is_assert()) property_id=source_location.get_property_id(); else if(step.pc->is_goto()) // unwinding, we suspect { property_id= id2string(step.pc->source_location.get_function())+ ".unwind."+std::to_string(step.pc->loop_number); } json_objectt &json_failure=dest_array.push_back().make_object(); json_failure["stepType"]=json_stringt("failure"); json_failure["hidden"]=jsont::json_boolean(step.hidden); json_failure["thread"]=json_numbert(std::to_string(step.thread_nr)); json_failure["reason"]=json_stringt(id2string(step.comment)); json_failure["property"]=json_stringt(id2string(property_id)); if(!json_location.is_null()) json_failure["sourceLocation"]=json_location; } break; case goto_trace_stept::typet::ASSIGNMENT: case goto_trace_stept::typet::DECL: { irep_idt identifier=step.lhs_object.get_identifier(); json_objectt &json_assignment=dest_array.push_back().make_object(); json_assignment["stepType"]=json_stringt("assignment"); if(!json_location.is_null()) json_assignment["sourceLocation"]=json_location; std::string value_string, binary_string, type_string, full_lhs_string; json_objectt full_lhs_value; if(step.full_lhs.is_not_nil()) full_lhs_string=from_expr(ns, identifier, step.full_lhs); #if 0 if(it.full_lhs_value.is_not_nil()) full_lhs_value_string=from_expr(ns, identifier, it.full_lhs_value); #endif if(step.full_lhs_value.is_not_nil()) full_lhs_value = json(step.full_lhs_value, ns); const symbolt *symbol; irep_idt base_name, display_name; if(!ns.lookup(identifier, symbol)) { base_name=symbol->base_name; display_name=symbol->display_name(); if(type_string=="") type_string=from_type(ns, identifier, symbol->type); json_assignment["mode"]=json_stringt(id2string(symbol->mode)); } json_assignment["value"]=full_lhs_value; json_assignment["lhs"]=json_stringt(full_lhs_string); json_assignment["hidden"]=jsont::json_boolean(step.hidden); json_assignment["thread"]=json_numbert(std::to_string(step.thread_nr)); json_assignment["assignmentType"]= json_stringt( step.assignment_type== goto_trace_stept::assignment_typet::ACTUAL_PARAMETER? "actual-parameter": "variable"); } break; case goto_trace_stept::typet::OUTPUT: { json_objectt &json_output=dest_array.push_back().make_object(); json_output["stepType"]=json_stringt("output"); json_output["hidden"]=jsont::json_boolean(step.hidden); json_output["thread"]=json_numbert(std::to_string(step.thread_nr)); json_output["outputID"]=json_stringt(id2string(step.io_id)); json_arrayt &json_values=json_output["values"].make_array(); for(const auto &arg : step.io_args) { if(arg.is_nil()) json_values.push_back(json_stringt("")); else json_values.push_back(json(arg, ns)); } if(!json_location.is_null()) json_output["sourceLocation"]=json_location; } break; case goto_trace_stept::typet::INPUT: { json_objectt &json_input=dest_array.push_back().make_object(); json_input["stepType"]=json_stringt("input"); json_input["hidden"]=jsont::json_boolean(step.hidden); json_input["thread"]=json_numbert(std::to_string(step.thread_nr)); json_input["inputID"]=json_stringt(id2string(step.io_id)); json_arrayt &json_values=json_input["values"].make_array(); for(const auto &arg : step.io_args) { if(arg.is_nil()) json_values.push_back(json_stringt("")); else json_values.push_back(json(arg, ns)); } if(!json_location.is_null()) json_input["sourceLocation"]=json_location; } break; case goto_trace_stept::typet::FUNCTION_CALL: case goto_trace_stept::typet::FUNCTION_RETURN: { std::string tag= (step.type==goto_trace_stept::typet::FUNCTION_CALL)? "function-call":"function-return"; json_objectt &json_call_return=dest_array.push_back().make_object(); json_call_return["stepType"]=json_stringt(tag); json_call_return["hidden"]=jsont::json_boolean(step.hidden); json_call_return["thread"]=json_numbert(std::to_string(step.thread_nr)); const symbolt &symbol=ns.lookup(step.identifier); json_objectt &json_function=json_call_return["function"].make_object(); json_function["displayName"]= json_stringt(id2string(symbol.display_name())); json_function["identifier"]=json_stringt(id2string(step.identifier)); json_function["sourceLocation"]=json(symbol.location); if(!json_location.is_null()) json_call_return["sourceLocation"]=json_location; } break; default: if(source_location!=previous_source_location) { // just the source location if(!json_location.is_null()) { json_objectt &json_location_only=dest_array.push_back().make_object(); json_location_only["stepType"]=json_stringt("location-only"); json_location_only["hidden"]=jsont::json_boolean(step.hidden); json_location_only["thread"]= json_numbert(std::to_string(step.thread_nr)); json_location_only["sourceLocation"]=json_location; } } } if(source_location.is_not_nil() && source_location.get_file()!="") previous_source_location=source_location; } }
void value_sett::output( const namespacet &ns, std::ostream &out) const { for(valuest::const_iterator v_it=values.begin(); v_it!=values.end(); v_it++) { irep_idt identifier, display_name; const entryt &e=v_it->second; if(has_prefix(id2string(e.identifier), "value_set::dynamic_object")) { display_name=id2string(e.identifier)+e.suffix; identifier=""; } else if(e.identifier=="value_set::return_value") { display_name="RETURN_VALUE"+e.suffix; identifier=""; } else { #if 0 const symbolt &symbol=ns.lookup(e.identifier); display_name=symbol.display_name()+e.suffix; identifier=symbol.name; #else identifier=id2string(e.identifier); display_name=id2string(identifier)+e.suffix; #endif } out << display_name; out << " = { "; const object_map_dt &object_map=e.object_map.read(); std::size_t width=0; for(object_map_dt::const_iterator o_it=object_map.begin(); o_it!=object_map.end(); o_it++) { const exprt &o=object_numbering[o_it->first]; std::string result; if(o.id()==ID_invalid || o.id()==ID_unknown) result=from_expr(ns, identifier, o); else { result="<"+from_expr(ns, identifier, o)+", "; if(o_it->second.offset_is_set) result+=integer2string(o_it->second.offset)+""; else result+='*'; if(o.type().is_nil()) result+=", ?"; else result+=", "+from_type(ns, identifier, o.type()); result+='>'; } out << result; width+=result.size(); object_map_dt::const_iterator next(o_it); next++; if(next!=object_map.end()) { out << ", "; if(width>=40) out << "\n "; } } out << " } " << std::endl; } }
void string_instrumentationt::invalidate_buffer( goto_programt &dest, goto_programt::const_targett target, const exprt &buffer, const typet &buf_type, const mp_integer &limit) { irep_idt cntr_id="string_instrumentation::$counter"; if(context.symbols.find(cntr_id)==context.symbols.end()) { symbolt new_symbol; new_symbol.base_name="$counter"; new_symbol.pretty_name=new_symbol.base_name; new_symbol.name=cntr_id; new_symbol.mode="C"; new_symbol.type=uint_type(); new_symbol.is_statevar=true; new_symbol.lvalue=true; new_symbol.static_lifetime=true; context.move(new_symbol); } const symbolt &cntr_sym=ns.lookup(cntr_id); // create a loop that runs over the buffer // and invalidates every element goto_programt::targett init=dest.add_instruction(ASSIGN); init->location=target->location; init->code=code_assignt(symbol_expr(cntr_sym), gen_zero(cntr_sym.type)); goto_programt::targett check=dest.add_instruction(); check->location=target->location; goto_programt::targett invalidate=dest.add_instruction(ASSIGN); invalidate->location=target->location; goto_programt::targett increment=dest.add_instruction(ASSIGN); increment->location=target->location; exprt plus("+", uint_type()); plus.copy_to_operands(symbol_expr(cntr_sym)); plus.copy_to_operands(gen_one(uint_type())); increment->code=code_assignt(symbol_expr(cntr_sym), plus); goto_programt::targett back=dest.add_instruction(); back->location=target->location; back->make_goto(check); back->guard=true_exprt(); goto_programt::targett exit=dest.add_instruction(); exit->location=target->location; exit->make_skip(); exprt cnt_bs, bufp; if(buf_type.id()=="pointer") bufp = buffer; else { index_exprt index; index.array()=buffer; index.index()=gen_zero(uint_type()); index.type()=buf_type.subtype(); bufp = address_of_exprt(index); } exprt deref("dereference", buf_type.subtype()); exprt b_plus_i("+", bufp.type()); b_plus_i.copy_to_operands(bufp); b_plus_i.copy_to_operands(symbol_expr(cntr_sym)); deref.copy_to_operands(b_plus_i); check->make_goto(exit); if(limit==0) check->guard= binary_relation_exprt(symbol_expr(cntr_sym), ">=", buffer_size(bufp)); else check->guard= binary_relation_exprt(symbol_expr(cntr_sym), ">", from_integer(limit, uint_type())); exprt nondet=side_effect_expr_nondett(buf_type.subtype()); invalidate->code=code_assignt(deref, nondet); }
void rd_range_domaint::transform( locationt from, locationt to, ai_baset &ai, const namespacet &ns) { reaching_definitions_analysist *rd= dynamic_cast<reaching_definitions_analysist*>(&ai); assert(rd!=0); assert(bv_container); // kill values if(from->is_dead()) transform_dead(ns, from); // kill thread-local values else if(from->is_start_thread()) transform_start_thread(ns, *rd); // do argument-to-parameter assignments else if(from->is_function_call()) transform_function_call(ns, from, to, *rd); // cleanup parameters else if(from->is_end_function()) transform_end_function(ns, from, to, *rd); // lhs assignements else if(from->is_assign()) transform_assign(ns, from, from, *rd); // initial (non-deterministic) value else if(from->is_decl()) transform_assign(ns, from, from, *rd); #if 0 // handle return values if(to->is_function_call()) { const code_function_callt &code=to_code_function_call(to->code); if(code.lhs().is_not_nil()) { rw_range_set_value_sett rw_set(ns, rd->get_value_sets()); goto_rw(to, rw_set); const bool is_must_alias=rw_set.get_w_set().size()==1; forall_rw_range_set_w_objects(it, rw_set) { const irep_idt &identifier=it->first; // ignore symex::invalid_object const symbolt *symbol_ptr; if(ns.lookup(identifier, symbol_ptr)) continue; assert(symbol_ptr!=0); const range_domaint &ranges=rw_set.get_ranges(it); if(is_must_alias && (!rd->get_is_threaded()(from) || (!symbol_ptr->is_shared() && !rd->get_is_dirty()(identifier)))) for(const auto &range : ranges) kill(identifier, range.first, range.second); } } }