Frama-C插件开发:获得价值分析的结果 [英] Frama-C Plugin development: Getting result of value-analysis
问题描述
我正在使用Value-analysis开发适用于Frama-C的插件. 我只是想在每个语句后打印变量(值)的状态(我认为解决方案很简单,但我无法弄清楚).
I am working on a Plugin for Frama-C, using the Value-analysis. I simply want to print the state of the variables (values) after each statement (I think the solution is quiet easy, but I couldn't figure it out).
我在访问者的vstmt_aux
方法中使用Db.Value.get_stmt_state
来获取当前状态.
I got the current state with Db.Value.get_stmt_state
in the vstmt_aux
method in the visitor.
现在如何获取变量的值?
How can I now get the values of the variables?
PS:我找到了这篇文章,但是它没有帮助,没有真正的解决方案,在描述的帮助下,我无法做到这一点:
PS: I found this post, but it didn't help, there is no real solution, and with the help of the description I was not able to do it: How to use functions in Value.Eval_expr, Value.Eval_op etc modules of Frama-c Value plugin
推荐答案
下面是一个具体示例,该示例如何针对每个局部变量和全局变量打印给定函数中每个语句之前Value所计算的结果(从从下到上):
Here's a concrete example of how to print, for each local and global variable, the result computed by Value before each statement in a given function (read the functions from bottom to top):
open Cil_types
(* Prints the value associated to variable [vi] before [stmt]. *)
let pretty_vi fmt stmt vi =
let kinstr = Kstmt stmt in (* make a kinstr from a stmt *)
let lval = (Var vi, NoOffset) in (* make an lval from a varinfo *)
let loc = (* make a location from a kinstr + an lval *)
!Db.Value.lval_to_loc kinstr ~with_alarms:CilE.warn_none_mode lval
in
Db.Value.fold_state_callstack
(fun state () ->
(* for each state in the callstack *)
let value = Db.Value.find state loc in (* obtain value for location *)
Format.fprintf fmt "%a -> %a@." Printer.pp_varinfo vi
Locations.Location_Bytes.pretty value (* print mapping *)
) () ~after:false kinstr
(* Prints the state at statement [stmt] for each local variable in [kf],
and for each global variable. *)
let pretty_local_and_global_vars kf fmt stmt =
let locals = Kernel_function.get_locals kf in
List.iter (fun vi -> pretty_vi fmt stmt vi) locals;
Globals.Vars.iter (fun vi _ -> pretty_vi fmt stmt vi)
(* Visits each statement in [kf] and prints the result of Value before the
statement. *)
class stmt_val_visitor kf =
object (self)
inherit Visitor.frama_c_inplace
method! vstmt_aux stmt =
(match stmt.skind with
| Instr _ ->
Format.printf "state for all variables before stmt: %a@.%a@."
Printer.pp_stmt stmt (pretty_local_and_global_vars kf) stmt
| _ -> ());
Cil.DoChildren
end
(* usage: frama-c file.c -load-script print_vals.ml *)
let () =
Db.Main.extend (fun () ->
Format.printf "computing value...@.";
!Db.Value.compute ();
let fun_name = "main" in
Format.printf "visiting function: %s@." fun_name;
let kf_vis = new stmt_val_visitor in
let kf = Globals.Functions.find_by_name fun_name in
let fundec = Kernel_function.get_definition kf in
ignore (Visitor.visitFramacFunction (kf_vis kf) fundec);
Format.printf "done!@.")
这远非理想,并且输出比仅使用Cvalue.Model.pretty state
更丑陋,但它可以作为进一步修改的基础.
This is far from ideal, and the output is uglier than simply using Cvalue.Model.pretty state
, but it could serve as base for further modifications.
此脚本已经过Frama-C镁的测试.
This script has been tested with Frama-C Magnesium.
要在语句后 检索状态,只需将fold_state_callstack
中的~after:false
参数替换为~after:true
.我以前的代码版本使用的函数已经为该前状态绑定了该值,但是没有为后状态导出该函数,因此我们必须使用fold_state_callstack
(附带地,它更强大,因为它允许检索每个调用堆栈的特定状态).
To retrieve the state after a statement, simply replace the ~after:false
parameter in fold_state_callstack
with ~after:true
. My previous version of the code used a function which already bound that value for the pre-state, but no such function is exported for the post-state, so we must use fold_state_callstack
(which is incidentally more powerful, because it allows retrieving a specific state per callstack).
这篇关于Frama-C插件开发:获得价值分析的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!