123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366(**************************************************************************)(* *)(* This file is part of the Frama-C's Luncov plug-in. *)(* *)(* Copyright (C) 2012-2022 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file LICENSE) *)(* *)(**************************************************************************)openCil_typesopenCommonstypeid=inttypeinfo={li_loc:Cil_types.location;li_tag:string;li_stmt:Cil_types.stmt;li_annotable:Cil_types.stmt;li_predicate:Cil_types.exp;li_kf:Cil_types.kernel_function;}moduleKFSet=Set.Make(structtypet=Cil_types.kernel_functionletcompare=compareend)moduleLabelInfo=Datatype.Make(structincludeDatatype.Serializable_undefinedtypet=infoletname="Instr.info_multicore"letreprs=[{li_loc=Cil_datatype.Location.unknown;li_tag="";li_stmt=Cil.dummyStmt;li_annotable=Cil.dummyStmt;li_predicate=Cil_datatype.Exp.dummy;li_kf=Kernel_function.dummy();}]letmem_project=Datatype.never_any_projectend)moduleH=Datatype.Int.HashtblmoduleLabelInfos=State_builder.Option_ref(Datatype.Triple(H.Make(LabelInfo))(H.Make(Datatype.Int))(H.Make(Datatype.Int)))(structletname="LabelInfos_multicore"letdependencies=[Ast.self]end)classlabel_mapperh=object(self)inheritVisitor.frama_c_inplacevalmutableopened_blocks=[]methodprivateget_parent_and_current=matchself#current_stmt,opened_blockswith|Somestmt,block::_->Some(block,stmt)|_->Nonemethod!vstmt_auxs=matchs.skindwith|Block_->opened_blocks<-s::opened_blocks;Cil.ChangeDoChildrenPost(s,funs->opened_blocks<-List.tlopened_blocks;s)|_->Cil.DoChildrenmethod!vinsti=beginmatchiwith|Call(None,{enode=(Lval(Var{vname=name},NoOffset))},idexp::cond::tagexp::_,loc)whenname=label_function_name->beginmatchCil.isIntegeridexp,cil_isStringtagexp,self#get_parent_and_currentwith|Someid,Sometag,Some(block_stmt,call_stmt)->letid=Integer.to_int_exnidinletenglobing_kf=Option.getself#current_kfinDatatype.Int.Hashtbl.addhid{li_loc=loc;li_tag=tag;li_stmt=block_stmt;li_annotable=call_stmt;li_predicate=cond;li_kf=englobing_kf;}|None,_,_->Options.warning"instr: invalid label at line %d [id]"(fstloc).Filepath.pos_lnum|_,None,_->Options.warning"instr: invalid label at line %d [tag]"(fstloc).Filepath.pos_lnum|_,_,None->Options.warning"instr: invalid label at line %d [structure]"(fstloc).Filepath.pos_lnumend|_->()end;Cil.SkipChildrenendletcompute():LabelInfos.data=letast=Ast.get()inleth=H.create97inVisitor.visitFramacFileSameGlobals(newlabel_mapperh)ast;letblocks=H.create97inletcalls=H.create97inletfidinfo=H.addblocksinfo.li_stmt.sidid;H.addcallsinfo.li_annotable.sidid;inH.iterfh;h,blocks,callsletcompute()=LabelInfos.memocomputeletget_label_ids()=lettable,_,_=compute()inH.fold(funk_l->k::l)table[]letgetid=lettable,_,_=compute()inH.findtableidletiterf=lettable,_,_=compute()inH.iterftableletget_locid=(getid).li_locletget_tagid=(getid).li_tagletget_stmtid=(getid).li_stmtletget_annotable_stmtid=(getid).li_annotableletget_predicateid=(getid).li_predicateletget_kfid=(getid).li_kfletis_annotable_stmt_by_sidsid=let_,_,calls=compute()inifH.memcallssidthenSome(H.findcallssid)elseNoneletis_annotable_stmtstmt=is_annotable_stmt_by_sidstmt.sidletis_stmt_by_sidsid=let_,blocks,_=compute()inifH.memblockssidthenSome(H.findblockssid)elseNoneletis_stmtstmt=is_stmt_by_sidstmt.sidletat=reftrue(** Emitter for uncoverable label's asertions *)letemitter=Emitter.create"Luncov_multicore"[Emitter.Code_annot]~correctness:[]~tuning:[](** Visitor that removes all but a single label (given its id),
add a single assertion whose validity implies the uncoverability of a label,
and provides information to get a Property.t
*)classlabel_selectorlblidinfoprj=object(self)inheritVisitor.frama_c_copyprjmethod!vinsti=beginmatchiwith|Call_->beginmatchself#current_stmtwith|Somestmt->beginmatchis_stmt_by_sidstmt.sidwith|Somelblid'whenlblid'<>lblid->stmt.skind<-Instr(Skip(Cil_datatype.Stmt.locstmt));Cil.SkipChildren|_->beginmatchis_annotable_stmt_by_sidstmt.sidwith|Somelblid'->iflblid'=lblidthen(self#add_label_annotstmt;Cil.JustCopy)elseCil.DoChildren|_->Cil.DoChildrenendend|_->Cil.DoChildrenend|_->Cil.DoChildrenend;methodprivateadd_label_annotnew_stmt=letlblinfo=getlblidinletcond=Cil.constFoldtrue(Visitor.visitFramacExpr(self:>Visitor.frama_c_visitor)lblinfo.li_predicate)inletcond=(Logic_utils.expr_to_term~coerce:truecond)inletrel=if!atthenCil_types.ReqelseCil_types.Rneqinletpred=Logic_const.prel(rel,cond,Cil.lzero())in(* NB negated*)lettop_pred=Logic_const.toplevel_predicate~kind:Checkpredinletold_kf=Option.getself#current_kfinletnew_kf=Visitor_behavior.Get.kernel_functionself#behaviorold_kfinletqueued_action()=letcode_annot=AAssert([],top_pred)inletcode_annotation=Logic_const.new_code_annotationcode_annotinAnnotations.add_code_annot~kf:new_kfemitternew_stmtcode_annotation;info:=Some(new_kf,new_stmt,code_annotation);inQueue.addqueued_actionself#get_filling_actionsendletcreate_project_for_label?nameid=letname=matchnamewithNone->"label_"^string_of_intid|Somename->nameinletinfo=refNoneinletprj=File.create_project_from_visitorname(newlabel_selectoridinfo)inmatch!infowith|Some(kf,stmt,code_annotation)->letip=Property.ip_of_code_annot_singlekfstmtcode_annotationinprj,Someip|None->prj,Noneletlbl_stmt_map=Hashtbl.create100letlbl_cond_map=Hashtbl.create100letlbl_kf_map=Hashtbl.create100letkf_lbl_map=Hashtbl.create100letget_kf_namekf=matchkf.fundecwith|Definition(f,_)->f.svar.vname|Declaration(_,f,_,_)->f.vnameletkfs=ref(KFSet.empty)letget_kf_lbl_partition()=(!kfs,kf_lbl_map)classlabel_collectorprj=object(self)inheritVisitor.frama_c_copyprjvalmutableinto_lbl_fun=falsemethod!vinsti=beginmatchiwith|Call_->beginmatchself#current_stmtwith|Somestmt->beginmatchis_annotable_stmt_by_sidstmt.sidwith|Somelblid->(* Saving info for writing label annotation *)Hashtbl.addlbl_stmt_maplblidstmt;letlblinfo=getlblidinletcond=Cil.constFoldtrue(Visitor.visitFramacExpr(self:>Visitor.frama_c_visitor)lblinfo.li_predicate)inletcond=(Logic_utils.expr_to_term~coerce:truecond)inletrel=if!atthenCil_types.ReqelseCil_types.Rneqinletassertion=Logic_const.prel(rel,cond,Cil.lzero())inHashtbl.addlbl_cond_maplblidassertion;letold_kf=Option.getself#current_kfinletnew_kf=Visitor_behavior.Get.kernel_functionself#behaviorold_kfinHashtbl.addlbl_kf_maplblidnew_kf;Hashtbl.addkf_lbl_map(get_kf_namenew_kf)lblid;kfs:=KFSet.addnew_kf!kfs;(* Replacing label by SKIP *)letreplace=(Skip(Cil_datatype.Stmt.locstmt))inCil.ChangeTo[replace]|_->Cil.DoChildrenend|_->Cil.DoChildrenend|_->Cil.DoChildrenend;endletcreated_project=refNoneletpreviously_processed_label=refNoneletold_project=refNoneletterminate()=match!old_projectwith|Somep->Project.set_currentp|None->()letcreate_project_=match!created_projectwith|Somep->Project.set_currentp;p|None->old_project:=Some(Project.current());letp=File.create_project_from_visitor"pr"(newlabel_collector)inCommons.copy_parametersp;created_project:=Somep;Project.set_currentp;pletadd_annotations_get_ipslabels=Annotations.iter_all_code_annot(funsea->Annotations.remove_code_annotesa);letips=Hashtbl.create(List.lengthlabels)inList.iter(funlblid->(* Adds new annotation *)try(letnew_stmt=Hashtbl.findlbl_stmt_maplblidinletpred=Hashtbl.findlbl_cond_maplblidinlettop_pred=Logic_const.toplevel_predicate~kind:Checkpredinletnew_kf=Hashtbl.findlbl_kf_maplblidinletcode_annot=AAssert([],top_pred)inletcode_annotation=Logic_const.new_code_annotationcode_annotinletemit=Emitter.create("Label"^(string_of_intlblid))[Emitter.Code_annot]~correctness:[]~tuning:[]inAnnotations.add_code_annot~kf:new_kfemitnew_stmtcode_annotation;(* Returns ip *)Hashtbl.addipslblid(Some(Property.ip_of_code_annot_singlenew_kfnew_stmtcode_annotation)))withNot_found->Hashtbl.addipslblidNone)labels;ipsletadd_annotation_get_iplblid=(* Removes previous annotation
(match !previously_processed_label with
| Some l -> let new_stmt = Hashtbl.find lbl_stmt_map l in
let assertion = Hashtbl.find lbl_cond_map l in
let new_kf = Hashtbl.find lbl_kf_map l in
let code_annot = AAssert ([], Check, assertion) in
let code_annotation = Logic_const.new_code_annotation code_annot in
Annotations.remove_code_annot emitter ~kf:new_kf new_stmt code_annotation ;
previously_processed_label := Some lblid
| None -> previously_processed_label := Some lblid); *)Annotations.iter_all_code_annot(funsea->Annotations.remove_code_annotesa);(* Adds new annotation *)try(letnew_stmt=Hashtbl.findlbl_stmt_maplblidinletpred=Hashtbl.findlbl_cond_maplblidinlettop_pred=Logic_const.toplevel_predicate~kind:Checkpredinletnew_kf=Hashtbl.findlbl_kf_maplblidinletcode_annot=AAssert([],top_pred)inletcode_annotation=Logic_const.new_code_annotationcode_annotinletemit=Emitter.create("Label"^(string_of_intlblid))[Emitter.Code_annot]~correctness:[]~tuning:[]inAnnotations.add_code_annot~kf:new_kfemitnew_stmtcode_annotation;(* Returns ip *)Some(Property.ip_of_code_annot_singlenew_kfnew_stmtcode_annotation))withNot_found->previously_processed_label:=None;None