在Frama-C中,是否可以自由指定基本类型的大小?
我的目标是TMS320F2808 DSP,具有16位字节。 char,short和int类型都是一个字节,long类型是两个。
到目前为止,我无法看到如果可能的话,我可以为Frama-C指定这些尺寸。
答案 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 == 16
,sizeof(int) == 1
和sizeof(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 … / 8
是8
代表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重新构建一点。
除int
和int64
外,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
。