@@ -466,32 +466,23 @@ struct
466466
467467 (* Give the set of reachables from argument. *)
468468 let reachables (ask : Queries.ask ) es =
469- let reachable acc e =
470- Option. bind acc (fun st ->
471- let ad = ask.f (Queries. ReachableFrom e) in
472- if Queries.AD. is_top ad then
473- None
474- else
475- Some (Queries.AD. join ad st))
469+ let reachable st e =
470+ let ad = ask.f (Queries. ReachableFrom e) in
471+ Queries.AD. join ad st
476472 in
477- List. fold_left reachable (Some ( Queries.AD. empty () )) es
473+ List. fold_left reachable (Queries.AD. empty () ) es
478474
479475
480476 let forget_reachable man st es =
481477 let ask = Analyses. ask_of_man man in
482478 let rs =
483- match reachables ask es with
484- | None ->
485- (* top reachable, so try to invalidate everything *)
486- let to_cil_lval x = Option. map Cil. var @@ RV. to_cil_varinfo x in
487- RD. vars st.rel |> List. filter_map to_cil_lval
488- | Some ad ->
489- let to_cil addr rs =
490- match addr with
491- | Queries.AD.Addr. Addr mval -> (ValueDomain.Addr.Mval. to_cil mval) :: rs
492- | _ -> rs
493- in
494- Queries.AD. fold to_cil ad []
479+ let ad = reachables ask es in
480+ let to_cil addr rs =
481+ match addr with
482+ | Queries.AD.Addr. Addr mval -> (ValueDomain.Addr.Mval. to_cil mval) :: rs
483+ | _ -> rs
484+ in
485+ Queries.AD. fold to_cil ad []
495486 in
496487 List. fold_left (fun st lval ->
497488 invalidate_one ask man st lval
@@ -512,6 +503,36 @@ struct
512503 if RD. is_bot_env res then raise Deadcode ;
513504 {st with rel = res}
514505
506+ let special_unknown_invalidate man f args =
507+ (* No warning here, base already produces the appropriate warnings *)
508+ let desc = LibraryFunctions. find f in
509+ let shallow_addrs = LibraryDesc.Accesses. find desc.accs { kind = Write ; deep = false } args in
510+ let deep_addrs = LibraryDesc.Accesses. find desc.accs { kind = Write ; deep = true } args in
511+ let deep_addrs =
512+ if List. mem LibraryDesc. InvalidateGlobals desc.attrs then (
513+ foldGlobals ! Cilfacade. current_file (fun acc global ->
514+ match global with
515+ | GVar (vi , _ , _ ) when not (BaseUtil. is_static vi) ->
516+ mkAddrOf (Var vi, NoOffset ) :: acc
517+ (* TODO: what about GVarDecl? *)
518+ | _ -> acc
519+ ) deep_addrs
520+ )
521+ else
522+ deep_addrs
523+ in
524+ let lvallist e =
525+ match man.ask (Queries. MayPointTo e) with
526+ | ad when Queries.AD. is_top ad -> []
527+ | ad ->
528+ Queries.AD. to_mval ad
529+ |> List. map ValueDomain.Addr.Mval. to_cil
530+ in
531+ let st' = forget_reachable man man.local deep_addrs in
532+ let shallow_lvals = List. concat_map lvallist shallow_addrs in
533+ List. fold_left (invalidate_one (Analyses. ask_of_man man) man) st' shallow_lvals
534+
535+
515536 let special man r f args =
516537 let ask = Analyses. ask_of_man man in
517538 let st = man.local in
@@ -542,31 +563,7 @@ struct
542563 assert_fn {man with local = st} (BinOp (Ge , Lval lv, zero, intType)) true
543564 ) st r
544565 | _ , _ ->
545- let lvallist e =
546- match ask.f (Queries. MayPointTo e) with
547- | ad when Queries.AD. is_top ad -> []
548- | ad ->
549- Queries.AD. to_mval ad
550- |> List. map ValueDomain.Addr.Mval. to_cil
551- in
552- let shallow_addrs = LibraryDesc.Accesses. find desc.accs { kind = Write ; deep = false } args in
553- let deep_addrs = LibraryDesc.Accesses. find desc.accs { kind = Write ; deep = true } args in
554- let deep_addrs =
555- if List. mem LibraryDesc. InvalidateGlobals desc.attrs then (
556- foldGlobals ! Cilfacade. current_file (fun acc global ->
557- match global with
558- | GVar (vi , _ , _ ) when not (BaseUtil. is_static vi) ->
559- mkAddrOf (Var vi, NoOffset ) :: acc
560- (* TODO: what about GVarDecl? *)
561- | _ -> acc
562- ) deep_addrs
563- )
564- else
565- deep_addrs
566- in
567- let st' = forget_reachable man st deep_addrs in
568- let shallow_lvals = List. concat_map lvallist shallow_addrs in
569- let st' = List. fold_left (invalidate_one ask man) st' shallow_lvals in
566+ let st' = special_unknown_invalidate man f args in
570567 (* invalidate lval if present *)
571568 Option. map_default (invalidate_one ask man st') st' r
572569
@@ -669,21 +666,19 @@ struct
669666
670667 let threadenter man ~multiple lval f args =
671668 let st = man.local in
669+ (* TODO: HACK: Simulate enter_multithreaded for first entering thread to publish global inits before analyzing thread.
670+ Otherwise thread is analyzed with no global inits, reading globals gives bot, which turns into top, which might get published...
671+ sync `Thread doesn't help us here, it's not specific to entering multithreaded mode.
672+ EnterMultithreaded events only execute after threadenter and threadspawn. *)
673+ if not (ThreadFlag. has_ever_been_multi (Analyses. ask_of_man man)) then
674+ ignore (Priv. enter_multithreaded (Analyses. ask_of_man man) man.global man.sideg st);
672675 match Cilfacade. find_varinfo_fundec f with
673676 | fd ->
674- (* TODO: HACK: Simulate enter_multithreaded for first entering thread to publish global inits before analyzing thread.
675- Otherwise thread is analyzed with no global inits, reading globals gives bot, which turns into top, which might get published...
676- sync `Thread doesn't help us here, it's not specific to entering multithreaded mode.
677- EnterMultithreaded events only execute after threadenter and threadspawn. *)
678- if not (ThreadFlag. has_ever_been_multi (Analyses. ask_of_man man)) then
679- ignore (Priv. enter_multithreaded (Analyses. ask_of_man man) man.global man.sideg st);
680677 let st' = Priv. threadenter (Analyses. ask_of_man man) man.global st in
681678 let new_rel = make_callee_rel ~thread: true man fd args in
682679 [{st' with rel = new_rel}]
683680 | exception Not_found ->
684- (* Unknown functions *)
685- (* TODO: do something like base? *)
686- failwith " relation.threadenter: unknown function"
681+ [special_unknown_invalidate man f args]
687682
688683 let threadspawn man ~multiple lval f args fman =
689684 man.local
0 commit comments