如何控制Frama-C中基本算术类型的大小?

时间:2013-11-19 23:01:14

标签: c frama-c

在Frama-C中,是否可以自由指定基本类型的大小?

我的目标是TMS320F2808 DSP,具有16位字节。 char,short和int类型都是一个字节,long类型是两个。

到目前为止,我无法看到如果可能的话,我可以为Frama-C指定这些尺寸。

2 个答案:

答案 0 :(得分:2)

您可能已经发现了-machdep选项。命令frama-c -machdep显示一个列表:

$ frama-c -machdep help
[kernel] supported machines are x86_64 x86_32 ppc_32 x86_16.

不幸的是,CHAR_BIT的值不是machdep参数之一。相反,值{8}在Frama-C中的CHAR_BIT的许多地方都是硬编码的。 添加对大于CHAR_BIT的8的值的支持是一项微不足道但重复的编程任务:必须简单地识别所有这些位置并修改它们以使用Bit_utils.sizeofchar()。事实上,有人已经这样做了,所以它绝对可行,但这种变化从未回馈给Frama-C开发(欢迎来到开源软件世界)。

完成上述操作后,使用CHAR_BIT == 16sizeof(int) == 1sizeof(long) == 2创建新架构将是一项相对简单的操作。

如何进行更改

我使用以下命令获得了第一个潜在变更网站列表。这会查找所有出现的数字8

$ grep -rI \\W8\\W src/*/*.ml
src/ai/base.ml: 8 (* FIXME: CHAR_BIT *), (String.length s)
src/aorai/aorai_register.ml:      (* Step 8 : clearing tables whose information has been
src/aorai/ltllexer.ml:  | 8 ->
src/aorai/promelalexer.ml:  | 8 ->
src/aorai/promelalexer_withexps.ml:  | 8 ->
src/aorai/yalexer.ml:  | 8 ->
src/gui/design.ml:    height * 8 / 5 (* 16/10 ratio *)
src/gui/gtk_form.ml:  val table = GPack.table ~rows:2 ~col_spacings:8 ~packing ()
src/gui/gtk_helper.ml:        ~fallback:"#neither UTF-8 nor locale nor ISO-8859-15#"
src/gui/gtk_helper.ml:        ~to_codeset:"UTF-8"
src/gui/source_manager.ml:(* Try to convert a source file either as UTF-8 or as locale. *)
src/kernel/stmts_graph.ml:    | Block _ -> [`Shape `Box; `Fontsize 8]
src/lib/binary_cache.ml:let cache_size () = 1 lsl (8 + MemoryFootprint.get ())
src/lib/bitvector.ml:  if b-a  [I 8]
src/logic/description.ml:  | IPPredicate(kind,kf,ki,_) -> [I 8;F kf;K ki] @ kind_order kind
src/logic/property.ml:    Hashtbl.hash (8, Kf.hash f, Kinstr.hash ki, hash_bhv_loop b)
src/logic/property_status.ml:                  | Never_tried -> [`Style `Bold; `Width 0.8 ]
src/memory_state/offsetmap.ml:    let char_width = 8 in
src/misc/bit_utils.ml:    Int_Base.inject (Int.of_int (warn_if_zero ty (bitsSizeOf ty) / 8))
src/pdg/ctrlDpds.ml:              (2) if (c) (3) y = 3; (4) goto L; else (5) z = 8;
src/pdg/ctrlDpds.ml:              (8) L : return x;
src/pdg/ctrlDpds.ml:    (1) -> (2) -> (6) -> (8)
src/printer/cil_printer.ml:    Integer.pred (Integer.of_int (8 * (Cil.bytesSizeOfInt k))) 
src/printer/cil_printer.ml:       CompoundInit (_, il) when List.length il >= 8 -> true
src/project/state_builder.ml:      debug ~level:8 "updating" p;
src/value/builtins_nonfree.ml:                Value_parameters.debug "find_ival(8) on %a returns %a" 
src/value/builtins_nonfree.ml:let int_hrange = Int.two_power_of_int (8 * Cil.theMachine.Cil.theMachine.sizeof_int -1)
src/value/builtins_nonfree_print_c.ml:        let step = if iso then 1 else (Integer.to_int modu) / 8 in
src/value/builtins_nonfree_print_c.ml:        let start = ref ((Integer.to_int bk) / 8) in
src/value/builtins_nonfree_print_c.ml:        let ek = ek / 8 in
src/value/eval_exprs.ml:                  let offs_bytes = fst (Cil.bitsOffset typ_exp offs) / 8 in
src/value/eval_terms.ml:                     [i * 8 * sizeof( *tlv)] *)
src/value/value_parameters.ml:            (defaults to 8; experimental)"
src/wp/Cint.ml:    in let hsb p = let n = p lsr 8 in if n = 0 then hsb.(p) else 8 + hsb.(n)
src/wp/GuiPanel.ml:  let options = GPack.hbox ~spacing:8 ~packing () in
src/wp/GuiPanel.ml:  let control = GPack.table ~columns:4 ~col_spacings:8 ~rows:2 ~packing () in
src/wp/Matrix.ml:  let buffer = Buffer.create 8 in
src/wp/cil2cfg.ml:    | VblkIn (Bloop s,_) -> (8, s.sid)
src/wp/ctypes.ml:  | 8 -> if signed then SInt64 else UInt64
src/wp/ctypes.ml:  | 8 -> Float64
src/wp/ctypes.ml:  | size -> WpLog.not_yet_implemented "%d-bits floats" (8*size)
src/wp/ctypes.ml:  let m = Array.create 8 None in
src/wp/ctypes.ml:     (Cil.bitsSizeOf ctype / 8)
src/wp/ctypes.ml:      (Cil.bitsSizeOf ctype / 8)
src/wp/driver.ml:  | 8 ->
src/wp/rformat.ml:  | 8 ->
src/wp/script.ml:  | 8 ->

第一个显然是真正的正面,第二个显然是假阳性。 在第一种情况下,上下文需要类型为int的值。最简单的变化是:

Index: src/ai/base.ml
===================================================================
--- src/ai/base.ml  (revision 24517)
+++ src/ai/base.ml  (working copy)
@@ -116,7 +116,7 @@
   let u, l = 
     match s with
     | CSString s ->
-   8 (* FIXME: CHAR_BIT *), (String.length s)
+   bitsSizeOf charType, (String.length s)
     | CSWstring s ->
    bitsSizeOf theMachine.wcharType, (List.length s)
   in

在上面的列表中,模式Cil.bitsSizeOf … / 88代表CHAR_BIT的确定信号,但在其他情况下,它需要查看源代码并了解意图。

困难来自常数8可能采取的不同形式。您可能还会遇到8L,相同的常量,但类型为int64。当该常量表示char的宽度时,可以用Int64.of_int (bitsSizeOf charType)替换它。 src / ai / base.ml中有一个:

Index: src/ai/base.ml
===================================================================
--- src/ai/base.ml  (revision 24517)
+++ src/ai/base.ml  (working copy)
@@ -156,12 +156,12 @@
     (fun _ x ->
        try Scanf.sscanf x "%Li-%Li"
          (fun min max ->
-            let mul8 = Int64.mul 8L in
+            let mul_CHAR_BIT = Int64.mul (Int64.of_int (bitsSizeOf charType)) in
             MinValidAbsoluteAddress.set
-              (Abstract_interp.Int.of_int64 (mul8 min));
+              (Abstract_interp.Int.of_int64 (mul_CHAR_BIT min));
             MaxValidAbsoluteAddress.set
               (Abstract_interp.Int.of_int64
-                 (Int64.pred (mul8 (Int64.succ max)))))
+                 (Int64.pred (mul_CHAR_BIT (Int64.succ max)))))
        with End_of_file | Scanf.Scan_failure _ | Failure _ as e ->
          Kernel.abort "Invalid -absolute-valid-range integer-integer: each integer may be in decimal, hexadecimal (0x, 0X), octal (0o) or binary (0b) notation and has to hold in 64 bits. A correct example is -absolute-valid-range 1-0xFFFFFF0.@\nError was %S@."
            (Printexc.to_string e))

然而,当使用命令行选项-absolute-valid-range时,影响最后一次更改会导致Frama-C崩溃,因为订单当前已初始化(前端尚未准备好回答有关大小的问题)解释命令行参数时char。所以这个特殊的变化必须推迟,并且必须注意该选项将继续假设8位字符,直到Frama-C重新构建一点。

intint64外,Frama-C还使用多精度(已分配)整数。该类型的常量8通常为Int.eight。可以用对Bit_utils.sizeofchar的调用替换这个,因为此函数返回一个多精度整数。还应检查代码的移位3。

答案 1 :(得分:1)

Frama-C使用了 machdep 的概念,它描述了底层的硬件架构。默认情况下,没有为您的情况提供合适的machdep,有时您可以自己制作并将其用于分析。不幸的是,这不是这种情况,因为您无法更改char的大小。

此答案的其余部分对原始问题没有帮助,因为char的大小目前无法在Frama-C中自定义。它留给想要为异国情调的架构配置Frama-C的人,但char的大小不是8位

对于默认的machdep不足的半香草体系结构,您可以使用以下内容创建文件machdep_custom.ml

module Mach = struct

  (* Contents of e.g. file cil/src/machdep_x86_32.ml properly modified for your
     architecture. The MSVC configuration is never used by Frama-C, no need
     to edit it (but it must be included). *)

  open Cil_types

  let gcc = {
    version_major    = 1;
    version_minor    = 0;
    version          = "custom machdep";
    (* All types but char and long long are 16 bits *)
    sizeof_short     = 2;
    sizeof_int       = 2;
    sizeof_long      = 2;
    sizeof_longlong  = 4;
  (* [...] *)
  }

end

let () = File.new_machdep "custom" (module Mach: Cil.Machdeps)

这将注册您自己的machdep。必须开始所有分析,将-load-script machdep_custom.ml -machdep custom添加到命令行。

由于技术原因,在Frama-C中,至少有一种类型必须是32位。在此示例中,您不能拥有sizeof(long long)=2