Frama-C插件开发:提取值分析结果为OCaml整数

时间:2016-04-01 03:24:27

标签: ocaml frama-c

我已阅读这两篇文章: Getting result of value analysisGetting the values of statement。这两篇文章提供了关于如何打印价值分析价值的宝贵信息。

但是,我的任务要求我提取存储在value变量中的整数,然后用整数做一些数学运算(我只关心整数值)。例如,如果某个变量的值分析结果是{1,2},我想将结果作为整数的OCaml列表得到:[1,2]。这样我就可以用它做数学。如果结果涉及间隔,我假设我可以定义一个类型来处理它。例如,

type point_or_interval =
| Point of int
| Interval of int * int

值变量的类型在文档中定义为type t = Cvalue.V.t。我无法在源代码中找到此模块,因此我不知道如何操作该值并提取我需要的信息。我该怎么做?我们将非常感谢代码插图!

编辑: 我试过以下代码。此代码是从Getting result of value analysis逐字复制的,只有pretty_vi函数中的一些修改。它不适用于我的测试输入程序 - Locations.Location_Bytes.find_lonely_key函数引发Not_found异常。我的输入程序也已附上。

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 *)
       let base, offset = Locations.Location_Bytes.find_lonely_key value in 
       (match offset with 
       | Ival.Set _ -> ()
       | Ival.Float _ -> ()
       | Ival.Top (_, _, _, _ )-> ());
       Format.fprintf fmt "%a -> %a@." Printer.pp_varinfo vi
         Db.Value.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!@.")

测试输入程序:

#include <stdio.h>

int main() {
    int a = 1;
    return 0;
}

此代码有什么问题?为什么找不到值的映射?

1 个答案:

答案 0 :(得分:3)

常规评论:如果您使用的是支持Merlin的编辑器,我认真推荐使用它。它可以更容易地找到定义了哪些模块,哪些类型是同义词,并且结合自动完成工具,Merlin可以让您更轻松地找到转换函数。

特别是,Merlin应该帮助您发现Cvalue.V.project_ival : V.t -> Ival.tV.t转换为Ival.t(假设该值是可转换的,例如它不是指针)。

Ival.t是一个复杂的区间值,可以表示:

  • 连续的浮点值间隔(Ival.Float);
  • 一小组整数值(Ival.Set);
  • 或实际的整数间隔(Ival.Top,尽管名称),带有同余信息和可选边界,例如: [9..--]1%4代表{x ∈ ℕ | x ≥ 9 ∧ x mod 4 = 1}

函数Ival.min_and_max : Ival.t -> Integer.t option * Integer.t option接受Ival.t并返回(假设间隔不包含浮点间隔)一对(maybe_min, maybe_max),其中maybe_minNone如果没有下限(减去无穷大),或者Some min则为maybe max,对称地为Ival.Set。它适用于Ival.TopInteger.t

请注意,var url = STREETVIEWURL var img = new Image(); // Add some info to prevent cross origin tainting img.src = url + '?' + new Date().getTime(); img.setAttribute('crossOrigin', ''); img.crossOrigin = "Anonymous"; img.onload = function() { var context = document.createElement('CANVAS').getContext('2d'); context.drawImage(img, 0, 0); //load 2 pixels. I chose the first one and the 5th row var data1 = context.getImageData(0, 0, 1, 1).data; var data2 = context.getImageData(0, 5, 1, 1).data; console.log(data1); // google unknown image is this pixel color [228,227,223,255] if(data1[0]==228 && data1[1]==227 && data1[2]==223 && data1[3]==255 && data2[0]==228 && data2[1]==227 && data2[2]==223 && data2[3]==255){ console.log("NO StreetView Available"); }else{ console.log("StreetView is Available"); } }; 不是机器整数,而是任意精度整数的实现。