Reputation: 1486
I'm developing a frama-c-plugin, where I want to get the values of pointers (not the address they are pointing to, but the value at that address).
This works so far for simple pointers. Now I want to handle pointers to pointers.
For example:
int k=12;
int *l=&k;
int **m = &l;
int ***n = &m;
When analyzing this code with my actual version, I get the values:
k=12
l=12
m=&k
n=&l
But I want these values:
k=12
l=12
m=12
n=12
Since they all reference the same memory location with the value 12 (over multiple references)
Now my question: Is it possible to get the bottom-value of m and n?
EDIT
Sorry for my bad description of the problem, I made a mistake in the Frama-C-GUI by clicking on the wrong variable, which made my question confusing. I removed this part of the initial question.
My code looks like this:
let rec rec_struct_solver vtype packed_fi vi_name act_offset=
match vtype with
| TComp( compinfo, bitsSizeofTypCache, attributes) ->(
if compinfo.cstruct then (
(*Do stuff for structs *)
)
)
| TNamed (typeinfo, attributes) ->(
(*Do Stuff for named types*)
)
| TPtr (typ1, attribute) -> (
let rec loc_match typ2=
match typ2 with
| TPtr(typ3, attribute) ->(
loc_match typ3
)
| TComp(_,_,_) -> (
rec_struct_solver typ2 None vi_name act_offset
)
| _ ->(
self#print_var_values stmt (Mem (Cil.evar vi), NoOffset) vi_name
)
in
loc_match typ1
| _ -> (*do something for others*)
So if the pointer points to another pointer, it should do the function loc_match recursivly, until it finds a struct or non-pointer-variable.
The outer function is called by: rec_struct_solver vtype None vi.vname NoOffset
I think the error is int the part (Mem(Cil.evar vi), NoOffset)
, because it only resolves the first pointer-step, but I don't know what else I should use as parameter to build an lval.
I hope the problem is now clearer.
Upvotes: 0
Views: 151
Reputation: 3422
The code below can be used to obtain a cil expression that dereferences a variable as much as possible. (Until the result is no longer a pointer.)
open Cil_types
let dummy_loc = Cil_datatype.Location.unknown
let mk_exp_lval lv = Cil.new_exp ~loc:dummy_loc (Lval lv)
(* Build ( *^n )e until [e] has no longer a pointer type.
invariant: typ == Cil.typeOf e *)
let rec deref typ e =
match Cil.unrollType typ with
| TPtr (typ_star_e, _) ->
let star_e (* *e *) = mk_exp_lval (Cil.mkMem e NoOffset) in
deref typ_star_e star_e
| _ -> e
(* Build ( *^n vi *)
let deref_vi vi =
deref vi.vtype (mk_exp_lval (Var vi, NoOffset))
Using your example, deref_vi vi_k
will return an expression that evaluates k
, while deref_vi vi_n
will return the Cil expression that corresponds to ***vi_n
. You should adapt your function to do more or less the same thing, especially in the case TPtr
Upvotes: 3