由于自定义machdep,Frama-C中的语法错误

时间:2017-02-01 14:23:30

标签: frama-c

我正在为我的应用程序使用MPLAB XC16 C编译器。如果我使用machdep x86_16,Frama-C正常工作。例如,我可以用这种方式发布Frama-C:

$ frama-c-gui machdep x86_16 -cpp-command 'C:\\"Program Files (x86)"\\Microchip\\xc16\\v1.26\\bin\\xc16-gcc.exe -E' -no-cpp-gnu-like D:\\project\\*.c

但是machdep x86_16并不完全符合XC16。所以我想定制machdep。
the instructions之后,我创建了包含以下内容的文件machdep_xc16.ml:

open Cil_types

let xc16 =
{
  version          = "dsPIC33F";
  compiler         = "XC16";    (* Compiler being used. *)
  sizeof_short     = 2;         (* Size of "short" *)
  sizeof_int       = 2;         (* Size of "int" *)
  sizeof_long      = 4;         (* Size of "long" *)
  sizeof_longlong  = 8;         (* Size of "long long" *)
  sizeof_ptr       = 2;         (* Size of pointers *)
  sizeof_float     = 4;         (* Size of "float" *)
  sizeof_double    = 4;         (* Size of "double" *)
  sizeof_longdouble  = 8;       (* Size of "long double" *)
  sizeof_void      = 0;         (* Size of "void" *)
  sizeof_fun       = 0;         (* Size of function *)
  size_t = "unsigned int";      (* Type of "sizeof(T)" *)
  wchar_t = "unsigned short";   (* Type of "wchar_t" *)
  ptrdiff_t = "int";            (* Type of "ptrdiff_t" *)
  alignof_short    = 2;         (* Alignment of "short" *)
  alignof_int      = 2;         (* Alignment of "int" *)
  alignof_long     = 2;         (* Alignment of "long" *)
  alignof_longlong = 2;         (* Alignment of "long long" *)
  alignof_ptr      = 2;         (* Alignment of pointers *)
  alignof_float    = 2;         (* Alignment of "float" *)
  alignof_double   = 2;         (* Alignment of "double" *)
  alignof_longdouble = 2;       (* Alignment of "long double" *)
  alignof_str      = 1;         (* Alignment of strings *)
  alignof_fun      = 1;         (* Alignment of function *)
  alignof_aligned  = 16;        (* Alignment of a type with aligned attribute *)
  char_is_unsigned = false;     (* Whether "char" is unsigned *)
  const_string_literals = true; (* Whether string literals have const chars *)
  little_endian = true;         (* whether the machine is little endian *)
  underscore_name = true;       (* If assembly names have leading underscore *)
  has__builtin_va_list = false; (* Whether [__builtin_va_list] is a known type *)
  __thread_is_keyword = false;  (* Whether [__thread] is a keyword *)
}

let mach2 = { xc16 with compiler = "baz" }

let () =
  let ran = ref false in
  Cmdline.run_after_loading_stage
    (fun () ->
       Kernel.result "Registering machdep 'xc16' as 'XC16'";
       File.new_machdep "XC16" xc16;
       if !ran then begin
         Kernel.result "Trying to register machdep 'mach2' as 'XC16'";
         File.new_machdep "XC16" mach2
       end
       else ran := true
    )

我在行#34之前的文件__fc_machdep.h中插入了以下行; #error必须定义..."

#ifdef __FC_MACHDEP_XC16
    #define  __FC_BYTE_ORDER __LITTLE_ENDIAN

    /* min and max values as specified in limits.h */
    #define __FC_SCHAR_MAX  0x7f
    #define __FC_SCHAR_MIN  (-__FC_SCHAR_MAX -1)
    #define __FC_UCHAR_MAX  0xff
    #define __FC_CHAR_MIN   __FC_SCHAR_MIN
    #define __FC_CHAR_MAX   __FC_SCHAR_MAX

    #define __FC_SHRT_MAX   0x7fff
    #define __FC_SHRT_MIN   (-__FC_SHRT_MAX -1)
    #define __FC_USHRT_MAX  0xffff
    #define __FC_INT_MAX    __FC_SHRT_MAX
    #define __FC_INT_MIN    __FC_SHRT_MIN
    #define __FC_UINT_MAX   __FC_USHRT_MAX

    #define __FC_LONG_MAX   0x7fffffff
    #define __FC_LONG_MIN   (-__FC_LONG_MAX -1)
    #define __FC_ULONG_MAX  0xffffffffU

    #define __FC_LLONG_MAX  0x7fffffffffffffffLL
    #define __FC_LLONG_MIN  (-__FC_LLONG_MAX -1)
    #define __FC_ULLONG_MAX 0xffffffffffffffffUL

    /* Required */
    #undef  __CHAR_UNSIGNED__
    #define __WORDSIZE 16                   
    #define __SIZEOF_SHORT 2
    #define __SIZEOF_INT 2
    #define __SIZEOF_LONG 4
    #define __SIZEOF_LONGLONG 8
    #define __CHAR_BIT 8
    #define __PTRDIFF_T int
    #define __SIZE_T unsigned int
    #define __FC_SIZE_MAX __FC_INT_MAX

    /* stdio.h */
    #define __FC_EOF (-1)
    #define __FC_FOPEN_MAX 8
    #define __FC_RAND_MAX 32767
    #define __FC_PATH_MAX 260
    #define __WCHAR_T unsigned short

    /* Optional */
    #define __INT8_T signed char
    #define __UINT8_T unsigned char
    #define __INT16_T signed int
    #define __UINT16_T unsigned int

    #define __INTPTR_T signed int
    #define __UINTPTR_T unsigned int
    #define __INT32_T signed long
    #define __UINT32_T unsigned long
    #define __INT64_T signed long long
    #define __UINT64_T unsigned long long

    /* Required */
    #define __INT_LEAST8_T signed char
    #define __UINT_LEAST8_T unsigned char
    #define __INT_LEAST16_T signed int
    #define __UINT_LEAST16_T unsigned int
    #define __INT_LEAST32_T signed long
    #define __UINT_LEAST32_T unsigned long
    #define __INT_LEAST64_T signed long long
    #define __UINT_LEAST64_T unsigned long long

    #define __INT_FAST8_T signed char
    #define __UINT_FAST8_T unsigned char
    #define __INT_FAST16_T signed int
    #define __UINT_FAST16_T unsigned int
    #define __INT_FAST32_T signed long
    #define __UINT_FAST32_T unsigned long
    #define __INT_FAST64_T signed long long
    #define __UINT_FAST64_T unsigned long long

    /* POSIX */
    #define __SSIZE_T signed long

    #define __FC_PTRDIFF_MIN __FC_INT_MIN 
    #define __FC_PTRDIFF_MAX __FC_INT_MAX
    #define __FC_VA_LIST_T char*

    /* Required */
    #define __INT_MAX_T signed long long
    #define __UINT_MAX_T unsigned long long
#else

现在,如果我以这种方式启动Frama-C:

$ frama-c-gui -load-script machdep_xc16 -machdep XC16 -cpp-command 'C:\\"Program Files (x86)"\\Microchip\\xc16\\v1.26\\bin\\xc16-gcc.exe -E' -no-cpp-gnu-like D:\\project\\*.c

我得到这样的输出:

[kernel] Registering machdep 'xc16' as 'XC16'
[kernel] Parsing .opam/4.02.3+mingw64c/share/frama-c/libc/__fc_builtin_for_normalization.i (no preprocessing)
[kernel] warning: machdep XC16 has no registered macro. Using __FC_MACHDEP_XC16 for pre-processing
[kernel] Parsing D:/project/main.c (with preprocessing)
. . .
[kernel] Parsing D:/project/get_data.c (with preprocessing)
[kernel] syntax error at .opam/4.02.3+mingw64c/share/frama-c/libc/__fc_define_wchar_t.h:28:
         26    #if !defined(__cplusplus)
         27    /* wchar_t is a keyword in C++ and shall not be a typedef. */
         28    typedef __WCHAR_T wchar_t;
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
         29    #else
         30    typedef __WCHAR_T fc_wchar_t;

处理包含#include <stdio.h>的文件时发生语法错误 我做错了什么?

1 个答案:

答案 0 :(得分:4)

有关如何添加新machdep的说明已在手册中进行了修订,并将在下一个Frama-C版本(Phosporus)上提供。

新machdep的主要问题是machdep有两个(看似多余的)部分:Frama-C使用的OCaml级定义,以及C预处理器在解析时使用的C级定义Frama-C标准库。认识到两者都是必需的和互补的,有助于理解为什么整个过程很麻烦(尽管将来会简化)。

以下是即将发布的说明摘录:

  

自定义机器描述可以如下实现:

let my_machine = {
  version          = "generic C compiler for my machine";
  compiler         = "generic";  (* may also be "gcc" or "msvc" *)
  cpp_arch_flags   = ["-m64"];
  sizeof_short     = 2;
  sizeof_int       = 4;
  sizeof_long      = 8;
  (* ... *)
}

let () = File.new_machdep "my_machine" my_machine

请注意,您的machdep_xc16.ml可以简化:您使用的代码是尝试注册两次相同machdep的测试的一部分,只是为了确保它失败。但实际上,当你使用-load-script时,你可以像上面一样直接创建machdep,直接调用File.new_machdep

  

加载此代码后,可以指示Frama-C使用新机器   使用-machdep命令行选项的模型。

     

如果您打算使用Frama-C的标准库标题,您还必须执行以下操作:

     
      
  • 定义常量__FC_MACHDEP_<CUSTOM>,替换<CUSTOM>   使用您创建的machdep的名称(大写字母);   这可以通过-cpp-extra-args="-D__FC_MACHDEP_<CUSTOM>";

  • 完成   
  • 提供一个头文件,其中包含与您的caml对应的宏定义   定义。在大多数情况下,这些是以__FC_为前缀的宏,   对应于标准C宏定义,例如,   __FC_UCHAR_MAX。 Frama-C使用这些定义   <limits.h>和其他标头提供标准C定义。   测试文件tests/misc/custom_machdep/__fc_machdep_custom.h   包含所需定义的完整示例。其他例子可以   可以在share/libc/__fc_machdep.h找到。

  •   
     

确保您的自定义标头定义__FC_MACHDEP   包括警卫,并且您正在分析的程序包括此标题   在所有其他标题之前。确保这一点的一种方法,无需修改任何   源文件是在GCC中使用-include等选项。

     

完整命令行的示例如下所示,用于自定义   machdep名为myarch,在文件my_machdep.ml中定义   使用machdep_myarch.h中定义的stdlib常量:

frama-c -load-script my_machdep.ml -machdep myarch \
   -cpp-extra-args="-D__FC_MACHDEP_MYARCH -include machdep_myarch.h"

请注意,Silicon中的__fc_machdep_custom.h不完整,但您发布的版本似乎已完成,因此请使用它:将其放在一个名为eg的文件中。 machdep_xc16.h,向其添加#define __FC_MACHDEP,并将其包含在其他文件之前,例如使用-include machdep_xc16.h作为预处理程序标志。这将确保使用您的machdep版本而不是Frama-C,这将允许您使用Frama-C的标准库以及根据您的体系结构定义的常量。

此外,由于您的命令行包含-cpp-command-no-cpp-gnu-like,因此您必须调整上面的-cpp-extra-args,直接将-D__FC_MACHDEP_MYARCH-include machdep_myarch.h放入你的-cpp-command