let modelCheck o_err_loc =
let module This_C_Abstraction =
Abstraction.Make_C_Abstraction(C_System_Descr)
in
let module This_Cf_C_Abstraction =
CfAbstraction.Make_C_Abstraction(C_System_Descr)
in
let module This_LMC = LazyModelChecker.Make_Lazy_Model_Checker(This_C_Abstraction) in
let module This_LMC_CF = CfLazyModelChecker.Make_Lazy_Model_Checker(This_Cf_C_Abstraction) in
let module Region = This_C_Abstraction.Region in
This_C_Abstraction.check_races := Options.getValueOfBool "checkRace";
This_C_Abstraction.assumed_invariants := Stats.time "read invariants" constructInvariants();
This_C_Abstraction.assumed_invariants_region := This_C_Abstraction.assumed_invariants_list_to_region();
let _ = This_LMC.process_env_assumptions (constructEnvironmentAssumptions ()) in
let seedPredsFile = Options.getValueOfString "pred" in
let seedPreds = Predicate.conjoinL (Stats.time "read seeds" constructInitialPredicates seedPredsFile)
in
let initStateFile = Options.getValueOfString "init" in
let initialState = Predicate.conjoinL (Stats.time "read initial state" constructInitialPredicates initStateFile) in
let mainFunctions = Options.getValueOfStringList "main" in
let killLabel = Options.getValueOfString "killLoc" in
let kill_location =
match (C_System_Descr.get_locations_at_label killLabel) with
[l] -> Some(l)
| [] ->
if (killLabel = "") then ()
else
Message.msg_string Message.Normal ("Kill label '" ^ killLabel ^
"' was not found in the source file(s)") ;
None
| _ ->
Message.msg_string Message.Error ("Kill label '" ^ killLabel ^
"' appears multiple times in the source file(s)") ;
exit 1
in
let killPreds = constructKillPredicates () in
let _ = This_C_Abstraction.initKill kill_location killPreds in
let _ = This_C_Abstraction.initialize_abstraction () in
let _ = Message.msg_string Message.Error "Done adding seed predicates" in
if (Options.getValueOfInt "predH" > 0) then
This_C_Abstraction.make_const_table () ;
Message.msg_string Message.Normal "\n\n\n********** Now running the model-checker **********\n\n" ;
flush stdout;
begin
let indent_loc = " " in
let print_op indent_op op =
let target_loc = C_System_Descr.get_target op
and c_command = C_System_Descr.get_command op
in
Message.msg_string Message.Normal
(indent_op ^ (C_Command.to_string c_command)) ;
Message.msg_string Message.Normal
(indent_loc ^ (C_System_Descr.location_to_string target_loc)) ;
match c_command.C_Command.code with
C_Command.FunctionCall _ ->
indent_op ^ " "
| C_Command.Block l ->
begin
match (List.hd (List.rev l)) with
| C_Command.Return _ ->
String.sub indent_op 0 ((String.length indent_op) - 3)
| _ -> indent_op
end
| _ -> indent_op
in
let mc_return_val =
try
if (Options.getValueOfBool "cf")
then
begin
let init_region =
let rec buildloclist lst loclist =
match lst with [] -> loclist
| a ::rest ->
try
buildloclist rest ((C_System_Descr.lookup_entry_location a) :: loclist)
with
Not_found ->
(Format.printf "Creating init_region: No function %s defined in program. Exiting\n" (a);
failwith ("No function "^(a)^" defined"))
in
let loclist = buildloclist mainFunctions [] in
This_Cf_C_Abstraction.create_region
loclist false seedPreds initialState
and error_region =
match o_err_loc with
| Some err_loc ->
if (Options.getValueOfBool "par") then
begin
let num_of_threads = List.length (Options.getValueOfStringList "main") in
Some (This_Cf_C_Abstraction.create_error_region err_loc num_of_threads Predicate.True)
end
else
Some (This_Cf_C_Abstraction.create_region [err_loc] true Predicate.True Predicate.True)
| None -> None
in let mc_return_val = This_LMC_CF.model_check init_region error_region
in match (mc_return_val) with
No_error ->
Message.msg_string Message.Normal "\n\nNo error found. The system is safe :-)\n"
| Error_reached (reg_i, op_list, reg_e) ->
Message.msg_string Message.Normal "\n\nError found! The system is unsafe :-(\n\n Error trace:\n" ;
Message.msg_printer Message.Normal This_Cf_C_Abstraction.Region.print reg_i ;
Message.msg_string Message.Normal "..\n\n" ;
Message.msg_string Message.Normal
(indent_loc ^ (C_System_Descr.location_to_string
(C_System_Descr.get_source (List.hd op_list)))) ;
let _ = List.fold_left print_op "" op_list in
Message.msg_string Message.Normal "\n\n" ;
Message.msg_printer Message.Normal This_Cf_C_Abstraction.Region.print reg_e;
if (Options.getValueOfBool "xml") then This_Cf_C_Abstraction.dumpXml op_list
| Race_condition ((reg1,oplist1, reg1'), (reg2, oplist2, reg2'), lv1, lv2) ->
Message.msg_string Message.Normal "\n\nRace condition found! The system is unsafe :-(\n\n\n";
Message.msg_string Message.Normal (Printf.sprintf "\n On the lvalues %s, %s \n" (Ast.Expression.lvalToString lv1) (Ast.Expression.lvalToString lv2));
Message.msg_string Message.Normal "Printing out the first trace.\n" ;
Message.msg_printer Message.Normal This_Cf_C_Abstraction.Region.print reg1 ;
Message.msg_string Message.Normal "\n\n" ;
Message.msg_string Message.Normal
(indent_loc ^ (C_System_Descr.location_to_string
(C_System_Descr.get_source (List.hd oplist1)))) ;
let _ = List.fold_left print_op "" oplist1 in
Message.msg_string Message.Normal "\n\n" ;
Message.msg_printer Message.Normal This_Cf_C_Abstraction.Region.print reg1';
if (Options.getValueOfBool "xml") then This_Cf_C_Abstraction.dumpXml oplist1 ;
Message.msg_string Message.Normal "\n\nPrinting out the second trace.\n" ;
Message.msg_printer Message.Normal This_Cf_C_Abstraction.Region.print reg2 ;
Message.msg_string Message.Normal "\n\n" ;
Message.msg_string Message.Normal
(indent_loc ^ (C_System_Descr.location_to_string
(C_System_Descr.get_source (List.hd oplist2)))) ;
let _ = List.fold_left print_op "" oplist2 in
Message.msg_string Message.Normal "\n\n" ;
Message.msg_printer Message.Normal This_Cf_C_Abstraction.Region.print reg2';
if (Options.getValueOfBool "xml") then This_Cf_C_Abstraction.dumpXml oplist2
end
else
begin
let init_region =
let rec buildloclist lst loclist =
match lst with [] -> loclist
| a ::rest ->
try
buildloclist rest ((C_System_Descr.lookup_entry_location a) :: loclist)
with
Not_found ->
(Format.printf "Creating init_region: No function %s defined in program. Exiting\n" (a);
failwith ("No function "^(a)^" defined"))
in
let loclist = buildloclist mainFunctions [] in
This_C_Abstraction.create_region
loclist false seedPreds initialState
and error_region =
match o_err_loc with
| Some err_loc ->
if (Options.getValueOfBool "par") then
begin
let num_of_threads = List.length (Options.getValueOfStringList "main") in
Some (This_C_Abstraction.create_error_region err_loc num_of_threads Predicate.True)
end
else
Some (This_C_Abstraction.create_region [err_loc] true Predicate.True Predicate.True)
| None -> None
in
let mc_return_val =
if (Options.getValueOfBool "checkRace")
then (This_LMC.model_check_tar init_region error_region)
else (This_LMC.model_check init_region error_region)
in match (mc_return_val) with
No_error ->
Message.msg_string Message.Normal "\n\nNo error found. The system is safe :-)\n"
| Error_reached (reg_i, op_list, reg_e) ->
Message.msg_string Message.Normal "\n\nError found! The system is unsafe :-(\n\n Error trace:\n" ;
Message.msg_string Message.Normal
(indent_loc ^ (C_System_Descr.location_to_string
(C_System_Descr.get_source (List.hd op_list)))) ;
let _ = List.fold_left print_op "" op_list in
Message.msg_string Message.Normal "\n\n" ;
Message.msg_printer Message.Normal This_C_Abstraction.Region.print reg_e;
if (Options.getValueOfBool "xml") then This_C_Abstraction.dumpXml op_list
| Race_condition ((reg1,oplist1, reg1'), (reg2, oplist2, reg2'), lv1, lv2) ->
Message.msg_string Message.Normal "\n\nRace condition found! The system is unsafe :-(\n\n\n";
Message.msg_string Message.Normal (Printf.sprintf "\n On the lvalues %s, %s \n" (Ast.Expression.lvalToString lv1) (Ast.Expression.lvalToString lv2));
Message.msg_string Message.Normal "Printing out the first trace.\n" ;
Message.msg_printer Message.Normal This_C_Abstraction.Region.print reg1 ;
Message.msg_string Message.Normal "\n\n" ;
Message.msg_string Message.Normal
(indent_loc ^ (C_System_Descr.location_to_string
(C_System_Descr.get_source (List.hd oplist1)))) ;
let _ = List.fold_left print_op "" oplist1 in
Message.msg_string Message.Normal "\n\n" ;
Message.msg_printer Message.Normal This_C_Abstraction.Region.print reg1';
if (Options.getValueOfBool "xml") then This_C_Abstraction.dumpXml oplist1 ;
Message.msg_string Message.Normal "\n\nPrinting out the second trace.\n" ;
Message.msg_printer Message.Normal This_C_Abstraction.Region.print reg2 ;
Message.msg_string Message.Normal "\n\n" ;
Message.msg_string Message.Normal
(indent_loc ^ (C_System_Descr.location_to_string
(C_System_Descr.get_source (List.hd oplist2)))) ;
let _ = List.fold_left print_op "" oplist2 in
Message.msg_string Message.Normal "\n\n" ;
Message.msg_printer Message.Normal This_C_Abstraction.Region.print reg2';
if (Options.getValueOfBool "xml") then This_C_Abstraction.dumpXml oplist2
end
with e ->
begin
This_C_Abstraction.dump_abs ();
Message.msg_string Message.Error ("Exception raised :("^(Printexc.to_string e));
raise e
end
in
()
end ;
Message.msg_string Message.Normal "\n\nPhi Regions:\n" ;
Message.msg_string Message.Normal (This_LMC.print_phis false) ;
Message.msg_string Message.Normal "\n\nModel checker stats:\n" ;
Message.msg_printer Message.Normal This_LMC.print_stats () ;
Message.msg_string Message.Normal "\n\nAbstractor stats:\n" ;
Message.msg_printer Message.Normal This_C_Abstraction.print_stats ()