Skip to content
Snippets Groups Projects
Commit 232282e6 authored by David Bühler's avatar David Bühler
Browse files

[Eva] The allocation builtins use the new callstack type.

parent 227e2ecd
No related branches found
No related tags found
No related merge requests found
...@@ -38,7 +38,7 @@ let wkey_imprecise_alloc = Self.register_warn_category ...@@ -38,7 +38,7 @@ let wkey_imprecise_alloc = Self.register_warn_category
module Base_hptmap = Hptmap.Make module Base_hptmap = Hptmap.Make
(Base.Base) (Base.Base)
(Value_types.Callstack) (Callstack)
(Hptmap.Comp_unused) (Hptmap.Comp_unused)
(struct let v = [ [ ] ] end) (struct let v = [ [ ] ] end)
(struct let l = [ Ast.self ] end) (struct let l = [ Ast.self ] end)
...@@ -57,9 +57,8 @@ let () = Ast.add_monotonic_state Dynamic_Alloc_Bases.self ...@@ -57,9 +57,8 @@ let () = Ast.add_monotonic_state Dynamic_Alloc_Bases.self
(* -------------------------- Auxiliary functions -------------------------- *) (* -------------------------- Auxiliary functions -------------------------- *)
let current_call_site () = let current_call_site () =
match Eva_utils.legacy_call_stack () with let callsite = Callstack.top_callsite (Eva_utils.current_call_stack ()) in
| (_kf, Kstmt stmt) :: _ -> stmt Option.value ~default:Cil.dummyStmt callsite
| _ -> Cil.dummyStmt
(* Remove some parts of the callstack: (* Remove some parts of the callstack:
- Remove the bottom of the call tree until we get to the call site - Remove the bottom of the call tree until we get to the call site
...@@ -67,29 +66,26 @@ let current_call_site () = ...@@ -67,29 +66,26 @@ let current_call_site () =
these call site correspond to a different use of a malloc function, these call site correspond to a different use of a malloc function,
so it is interesting to keep their bases separated. *) so it is interesting to keep their bases separated. *)
let call_stack_no_wrappers () = let call_stack_no_wrappers () =
let stack = Eva_utils.legacy_call_stack () in let cs = Eva_utils.current_call_stack () in
assert (stack != []); let wrappers = Parameters.AllocFunctions.get () in
let wrappers = Parameters.AllocFunctions.get() in
let rec bottom_filter = function let rec bottom_filter = function
| [] -> assert false | [] | [_] as stack -> stack
| [_] as stack -> stack (* Do not empty the stack completely *)
| (kf,_)::((kf', _):: _ as rest) as stack -> | (kf,_)::((kf', _):: _ as rest) as stack ->
if Datatype.String.Set.mem (Kernel_function.get_name kf) wrappers then if Datatype.String.Set.mem (Kernel_function.get_name kf) wrappers
if Datatype.String.Set.mem (Kernel_function.get_name kf') wrappers then && Datatype.String.Set.mem (Kernel_function.get_name kf') wrappers
bottom_filter rest then bottom_filter rest
else else stack
stack
else
stack
in in
bottom_filter stack { cs with stack = bottom_filter cs.stack }
let register_malloced_base ?(stack=call_stack_no_wrappers ()) b = let register_malloced_base ~stack b =
let stack_without_top = List.tl stack in let stack_without_top =
Option.value ~default:stack (Callstack.pop stack)
in
Dynamic_Alloc_Bases.set Dynamic_Alloc_Bases.set
(Base_hptmap.add b stack_without_top (Dynamic_Alloc_Bases.get ())) (Base_hptmap.add b stack_without_top (Dynamic_Alloc_Bases.get ()))
let fold_dynamic_bases (f: Base.t -> Value_types.Callstack.t -> 'a -> 'a) init = let fold_dynamic_bases (f: Base.t -> Callstack.t -> 'a -> 'a) init =
Base_hptmap.fold f (Dynamic_Alloc_Bases.get ()) init Base_hptmap.fold f (Dynamic_Alloc_Bases.get ()) init
let is_automatically_deallocated base = let is_automatically_deallocated base =
...@@ -120,20 +116,17 @@ let extract_size sizev_bytes = ...@@ -120,20 +116,17 @@ let extract_size sizev_bytes =
(* Name of the base that will be given to a malloced variable, determined (* Name of the base that will be given to a malloced variable, determined
using the callstack. *) using the callstack. *)
let base_name prefix stack = let base_name prefix cs =
let stmt_line stmt = (fst (Cil_datatype.Stmt.loc stmt)).Filepath.pos_lnum in let stmt_line stmt = (fst (Cil_datatype.Stmt.loc stmt)).Filepath.pos_lnum in
match stack with match cs.Callstack.stack with
| [] -> assert false | [] ->
| [kf, Kglobal] -> (* Degenerate case *) (* Degenerate case *)
Format.asprintf "__%s_%a" prefix Kernel_function.pretty kf Format.asprintf "__%s_%a" prefix Kernel_function.pretty cs.entry_point
| (_, Kglobal) :: _ :: _ -> assert false | (_, callsite) :: qstack ->
| (_, Kstmt callsite) :: qstack ->
(* Use the whole call-stack to generate the name *) (* Use the whole call-stack to generate the name *)
let rec loop_full = function let rec loop_full = function
| [_, Kglobal] -> Format.sprintf "_%s" (Kernel.MainFunction.get ()) | [] -> Format.sprintf "_%s" (Kernel_function.get_name cs.entry_point)
| (_, Kglobal) :: _ :: _ -> assert false | (kf, line) :: b ->
| [] -> assert false (* impossible, we should have seen a Kglobal *)
| (kf, Kstmt line)::b ->
let line = stmt_line line in let line = stmt_line line in
let node_str = Format.asprintf "_l%d__%a" let node_str = Format.asprintf "_l%d__%a"
line Kernel_function.pretty kf line Kernel_function.pretty kf
...@@ -141,14 +134,14 @@ let base_name prefix stack = ...@@ -141,14 +134,14 @@ let base_name prefix stack =
(loop_full b) ^ node_str (loop_full b) ^ node_str
in in
(* Use only the name of the caller to malloc for the name *) (* Use only the name of the caller to malloc for the name *)
let caller = function let caller =
| [] -> assert false (* caught above *) let kf = Callstack.top_kf { cs with stack = qstack } in
| (kf, _) :: _ -> Format.asprintf "_%a" Kernel_function.pretty kf Format.asprintf "_%a" Kernel_function.pretty kf
in in
let full_name = false in let full_name = false in
Format.asprintf "__%s%s_l%d" Format.asprintf "__%s%s_l%d"
prefix prefix
(if full_name then loop_full qstack else caller qstack) (if full_name then loop_full qstack else caller)
(stmt_line callsite) (stmt_line callsite)
type var = Weak | Strong type var = Weak | Strong
...@@ -217,7 +210,7 @@ let guess_intended_malloc_type stack sizev constant_size = ...@@ -217,7 +210,7 @@ let guess_intended_malloc_type stack sizev constant_size =
| _ -> raise Exit | _ -> raise Exit
in in
try try
match snd (List.hd stack) with match snd (Callstack.top_call stack) with
| Kstmt {skind = Instr (Call (Some lv, _, _, _))} -> | Kstmt {skind = Instr (Call (Some lv, _, _, _))} ->
mk_typed_size (Cil.typeOfLval lv) mk_typed_size (Cil.typeOfLval lv)
| Kstmt {skind = Instr(Local_init(vi, _, _))} -> mk_typed_size vi.vtype | Kstmt {skind = Instr(Local_init(vi, _, _))} -> mk_typed_size vi.vtype
...@@ -380,7 +373,7 @@ let string_of_region = function ...@@ -380,7 +373,7 @@ let string_of_region = function
(* Only called when the 'weakest base' needs to be allocated. *) (* Only called when the 'weakest base' needs to be allocated. *)
let create_weakest_base region = let create_weakest_base region =
let stack = [ fst (Globals.entry_point ()), Kglobal ] in let stack = { (Eva_utils.current_call_stack ()) with stack = [] } in
let type_base = let type_base =
TArray (Cil.charType, None, []) TArray (Cil.charType, None, [])
in in
...@@ -413,8 +406,8 @@ let alloc_weakest_base region = ...@@ -413,8 +406,8 @@ let alloc_weakest_base region =
stack. Currently, the callstacks are truncated according to stack. Currently, the callstacks are truncated according to
[-eva-alloc-functions]. *) [-eva-alloc-functions]. *)
module MallocedByStack = (* varinfo list Callstack.hashtbl *) module MallocedByStack = (* varinfo list Callstack.hashtbl *)
State_builder.Hashtbl(Value_types.Callstack.Hashtbl) State_builder.Hashtbl (Callstack.Hashtbl)
(Datatype.List(Base)) (Datatype.List (Base))
(struct (struct
let name = "Value.Builtins_malloc.MallocedByStack" let name = "Value.Builtins_malloc.MallocedByStack"
let size = 17 let size = 17
...@@ -686,7 +679,7 @@ let free_automatic_bases stack state = ...@@ -686,7 +679,7 @@ let free_automatic_bases stack state =
let bases_to_free = let bases_to_free =
Base_hptmap.fold (fun base stack' acc -> Base_hptmap.fold (fun base stack' acc ->
if is_automatically_deallocated base && if is_automatically_deallocated base &&
Value_types.Callstack.equal stack stack' Callstack.equal stack stack'
then Base.Hptset.add base acc then Base.Hptset.add base acc
else acc else acc
) (Dynamic_Alloc_Bases.get ()) Base.Hptset.empty ) (Dynamic_Alloc_Bases.get ()) Base.Hptset.empty
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
(** Dynamic allocation related builtins. (** Dynamic allocation related builtins.
Most functionality is exported as builtins. *) Most functionality is exported as builtins. *)
val fold_dynamic_bases: (Base.t -> Value_types.Callstack.t -> 'a -> 'a) -> 'a -> 'a val fold_dynamic_bases: (Base.t -> Callstack.t -> 'a -> 'a) -> 'a -> 'a
(** [fold_dynamic_bases f init] folds [f] to each dynamically allocated base, (** [fold_dynamic_bases f init] folds [f] to each dynamically allocated base,
with initial accumulator [init]. with initial accumulator [init].
Note that this also includes bases created by [alloca] and [VLAs]. *) Note that this also includes bases created by [alloca] and [VLAs]. *)
...@@ -34,7 +34,7 @@ val alloc_size_ok: Cvalue.V.t -> Alarmset.status ...@@ -34,7 +34,7 @@ val alloc_size_ok: Cvalue.V.t -> Alarmset.status
small enough, [False] that the allocation is guaranteed to fail (because small enough, [False] that the allocation is guaranteed to fail (because
the size is always greater than SIZE_MAX). *) the size is always greater than SIZE_MAX). *)
val free_automatic_bases: Value_types.Callstack.t -> Cvalue.Model.t -> Cvalue.Model.t val free_automatic_bases: Callstack.t -> Cvalue.Model.t -> Cvalue.Model.t
(** Performs the equivalent of [free] for each location that was allocated via (** Performs the equivalent of [free] for each location that was allocated via
[alloca()] in the current function (as per [Eva_utils.call_stack ()]). [alloca()] in the current function (as per [Eva_utils.call_stack ()]).
This function must be called during finalization of a function call. *) This function must be called during finalization of a function call. *)
...@@ -44,7 +44,3 @@ val freeable: Cvalue.V.t -> Abstract_interp.truth ...@@ -44,7 +44,3 @@ val freeable: Cvalue.V.t -> Abstract_interp.truth
value points to an allocated memory block that can be safely released using value points to an allocated memory block that can be safely released using
the C function free. Note that \freeable(\null) does not hold, despite NULL the C function free. Note that \freeable(\null) does not hold, despite NULL
being a valid argument to the C function free. *) being a valid argument to the C function free. *)
(**/**)
val register_malloced_base: ?stack:Value_types.Callstack.t -> Base.t -> unit
(* Should not be used by casual users. *)
...@@ -92,7 +92,7 @@ let memcpy_check_indeterminate_offsetmap offsm = ...@@ -92,7 +92,7 @@ let memcpy_check_indeterminate_offsetmap offsm =
currently called function. *) currently called function. *)
let deps_nth_arg n = let deps_nth_arg n =
let open Function_Froms in let open Function_Froms in
let (kf,_) = List.hd (Eva_utils.legacy_call_stack()) in let kf = Callstack.top_kf (Eva_utils.current_call_stack ()) in
try try
let vi = List.nth (Kernel_function.get_formals kf) n in let vi = List.nth (Kernel_function.get_formals kf) n in
Deps.add_data_dep Deps.bottom (Locations.zone_of_varinfo vi) Deps.add_data_dep Deps.bottom (Locations.zone_of_varinfo vi)
......
...@@ -214,8 +214,9 @@ let finalize_call stmt call _recursion ~pre:_ ~post:state = ...@@ -214,8 +214,9 @@ let finalize_call stmt call _recursion ~pre:_ ~post:state =
To minimize computations, only do it for function definitions. *) To minimize computations, only do it for function definitions. *)
let state' = let state' =
if Kernel_function.is_definition call.kf then if Kernel_function.is_definition call.kf then
let stack = (call.kf, Kstmt stmt) :: (Eva_utils.legacy_call_stack ()) in let callstack = Eva_utils.current_call_stack () in
Builtins_malloc.free_automatic_bases stack state let callstack = Callstack.push call.kf stmt callstack in
Builtins_malloc.free_automatic_bases callstack state
else state else state
in in
`Value state' `Value state'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment