Model non-deterministic value integer in Frama-C - frama-c

Could anyone please tell me is this the right model for non-deterministic values of integer and unsigned integer in Frama-C?
/* Suppose Frama-C is installed in /usr/local -default prefix */
#include "/usr/local/share/frama-c/builtin.h"
#include "/usr/local/share/frama-c/libc/limits.h"
...
#define nondet_int() Frama_C_interval(INT_MIN, INT_MAX)
#define nondet_uint() Frama_C_interval(0, UINT_MAX)
...
Are there any exceptions if I use the above code with different architectures in option -machdep?

No, in the Neon version you have to manually define the appropriate macro if you want to use another -machdep. You would typically end up with a command-line like that:
frama-c -cpp-extra-args="-D__FC_MACHDEP_X86_64" -machdep x86_64
Forthcoming Sodium release will make the -cpp-extra-args unnecessary, as well as providing by default a -I option to let preprocessor search into Frama-C's libc header, so that you won't have to provide it yourself or rely on absolute paths in your #include directive
NB: This answer is not a commitment to any particular date for the Sodium release.

One reason Frama_C_interval(0, UINT_MAX) may not work as intended is that Frama_C_interval has type int (int, int). When you happen to want the entire range of unsigned int values, that actually tends to help because the conversions that are introduced are subject to approximation, but in general the fact that Frama_C_interval is declared as returning an int is a nuisance.
The latest released version already has Frama_C_unsigned_int_interval, but it is in share/libc/__fc_builtin.h (installed to /usr/local/share/frama-c/libc/__fc_builtin.h. The file builtin.h looks like a vestigial remnant, especially with the $Id$ line dating back to when development was done under SVN.
For specifying that a value should be all possible unsigned intvalues, Frama_C_unsigned_int_interval(0, -1) saves yourself the trouble of including limit.h. The int value -1 passed as argument is converted to the largest unsigned int as per C rules.

Related

mpi4py Split_type using openmpi's OMPI_COMM_TYPE_SOCKET

Is it possible to split a communicator using openmpi's OMPI_COMM_TYPE_SOCKET in mpi4py?
I've verified this works:
from mpi4py import MPI
comm = MPI.COMM_WORLD
sharedcomm = comm.Split_type(MPI.COMM_TYPE_SHARED)
but this does not:
socketcomm = comm.Split_type(MPI.OMPI_COMM_TYPE_SOCKET)
nor does this:
socketcomm = comm.Split_type(MPI.COMM_TYPE_SOCKET)
I've looked at the docs but I can't find anything about this.
mpi4py only provides a wrapper around standard MPI features. OMPI_COMM_TYPE_SOCKET is an Open MPI specific split type. You may still use it in mpi4py if you know its numeric value as it is just a member of a C enum:
/*
* Communicator split type constants.
* Do not change the order of these without also modifying mpif.h.in
* (see also mpif-common.h.fin).
*/
enum {
MPI_COMM_TYPE_SHARED,
OMPI_COMM_TYPE_HWTHREAD,
OMPI_COMM_TYPE_CORE,
OMPI_COMM_TYPE_L1CACHE,
OMPI_COMM_TYPE_L2CACHE,
OMPI_COMM_TYPE_L3CACHE,
OMPI_COMM_TYPE_SOCKET, // here
OMPI_COMM_TYPE_NUMA,
OMPI_COMM_TYPE_BOARD,
OMPI_COMM_TYPE_HOST,
OMPI_COMM_TYPE_CU,
OMPI_COMM_TYPE_CLUSTER
};
#define OMPI_COMM_TYPE_NODE MPI_COMM_TYPE_SHARED
Being a member of an enum means that the actual numerical value of OMPI_COMM_TYPE_SOCKET depends on its position in the enum and hence may differ from one release of Open MPI to another. You have several options here.
Hardcode the value
This is the simplest option. Open mpi.h (ompi_info --path incdir gives you its location), count the position of OMPI_COMM_TYPE_SOCKET in the enclosing enum starting with 0 for MPI_COMM_TYPE_SHARED and hardcode the value. The code may break with releases of Open MPI different from yours.
Parse mpi.h
Read mpi.h, search for enum definitions and find the one containing OMPI_COMM_TYPE_SOCKET. Provided that MPI_COMM_TYPE_SHARED is 0, the value of OMPI_COMM_TYPE_SOCKET is its 0-based index in the sequence of enum values. This depends a lot on the code in mpi.h having a specific format and can easily break if that changes.
Parse mpif.h
The Fortran interface is easier to parse as there the value is defined as:
parameter (OMPI_COMM_TYPE_SOCKET=6)
This is easily parsable with a simple regular expression. The problem is that recent versions of Open MPI split mpif.h over a couple of files that are then included from mpif.h and currently the value is in mpif-constants.h. So you may need to parse the include statements and recurse into the files they reference. Note that those are Fortran include statements and not preprocessor #include directives.
Code generation
Write a small C program that outputs the value of OMPI_COMM_TYPE_SOCKET to a Python file and run it as part of your program's setup procedure. Something like:
#include <stdio.h>
#include <mpi.h>
int main (int argc, char **argv)
{
if (argc != 2)
{
printf("Usage: mkompimod /path/to/module.py\n");
return 1;
}
FILE *fh = fopen(argv[1], "w");
if (fh != NULL) {
fprintf(fh, "COMM_TYPE_SOCKET = %d\n", OMPI_COMM_TYPE_SOCKET);
fclose(fh);
}
return 0;
}
Put that in a file named mkompimod.c. Compile with mpicc -o mkompimod mkompimod.c and run with mkompimod /path/to/ompi.py to create a Python file ompi.py with the value of OMPI_COMM_TYPE_SOCKET. Import it and use it in the call to comm.Split_type():
import ompi
socketcomm = comm.Split_type(ompi.COMM_TYPE_SOCKET)
Write a Python module in C
That's a bit involved, but you can write a C module that includes mpi.h and exports the value of OMPI_COMM_TYPE_SOCKET as a Python constant. Consult the Python documentation on how to write extensions in C.
Use the CFFI module
CFFI lets you build Python modules that wrap C libraries and writes all the glue code for you. Put the following in a file named ompi_build.py:
from cffi import FFI
ffi = FFI()
ffi.set_source("ompi", r"#include <mpi.h>")
ffi.cdef(
r"""
const int OMPI_COMM_TYPE_HWTHREAD;
... more constants here ...
const int OMPI_COMM_TYPE_SOCKET;
... even more constants here ...
"""
)
if __name__ == "__main__":
ffi.compile(verbose=True)
Run like this:
$ CC=mpicc python ompi_build.py
This will create the C module ompi.c and compile it into a loadable DSO. You may then import it and access the constant like this:
from ompi.lib import OMPI_COMM_TYPE_SOCKET
socketcomm = comm.Split_type(OMPI_COMM_TYPE_SOCKET)
CFFI provides integration with Python's distutils and you can have it automatically build the C module as part of the setup process.
Use Cython
That's what mpi4py itself is written in. It blends C and Python into a single cryptic syntax. Read the source code. Try to figure out what's going on and how to write something yourself. Can't help you there.
Whichever path you choose, keep in mind that all this pertains to the system on which the program will be running, not only the system on which the program will be developed.

Frama-C aborted Invalid user input

I am very new to Frama-c and I got an issue when I am trying to open a C source file.
The error shows as
"fatal error: event.h: No such file or directory. Compilation terminated".
[kernel] Parsing FRAMAC_SHARE/libc/__fc_builtin_for_normalization.i (no preprocessing)
[kernel] Parsing WorkSpace/bipbuffer.c (with preprocessing)
[kernel] user error: failed to run: gcc -E -C -I. -dD -D__FRAMAC__ -nostdinc -D__FC_MACHDEP_X86_32 -I/usr/share/frama-c/libc -o '/tmp/bipbuffer.ce6d077.i' '/home/xxx/WorkSpace/bipbuffer.c' you may set the CPP environment variable to select the proper preprocessor command or use the option "-cpp-command".
[kernel] user error: stopping on file "/home/xxx/WorkSpace/bipbuffer.c" that has errors. Add'-kernel-msg-key pp' for preprocessing command.
So bascially I am trying to open a C source file but it returns an error like this. I aslo tried other very simple C files like hello world and other slicing functions, it works well.
I thought it was because I didn't have the dependencies of 'event.h' but it still return these errors after I installed the libevent dependencies. I am not sure if I need to manually set some path of the dependencies for frama-c
Here is part of the C file (Source link: https://memcached.org/) that I would like to open:
#include "stdio.h"
#include <stdlib.h>
/* for memcpy */
#include <string.h>
#include "bipbuffer.h"
static size_t bipbuf_sizeof(const unsigned int size)
{
return sizeof(bipbuf_t) + size;
}
int bipbuf_unused(const bipbuf_t* me)
{
if (1 == me->b_inuse)
/* distance between region B and region A */
return me->a_start - me->b_end;
else
return me->size - me->a_end;
}
......
Thanks,
Compilers and other tools working with C source code need to know where to find header files. There are some standard places where they look automatically, but Frama-C has fewer of those than (and different ones from) a normal compiler.
You need to find out where event.h is installed, then pass something like -cpp-extra-args "-I /path/to/directory/" to Frama-C. Pass the directory name only, not including the name event.h itself.
In addition to Isabelle Newbie's answer, I'd like to point out that the Chlorine version of Frama-C, whose beta has been recently announced, features a new option -json-compilation-database that attempts to read the arguments to be passed to the pre-processor from a compilation database.
Such database can be generated directly by cmake, but there are solutions for make-based project such as the one you refer to, in particular bear, which intercepts the commands launched by make to build the database.
Here's a detailed summary of how you could proceed, using the new -json-compilation-database option from Frama-C 17 Chlorine, plus an extra script list_files.py (which is not in the beta, but will be available in the final 17 release, and can be downloaded here):
Get the source files you want to analyze with Frama-C, run ./configure, and if possible try to disable optional dependencies from external libraries; for instance, some code bases include optional dependencies based on availability of libraries/system features, but have fallback options (resorting to standard C library or POSIX functions). The more you give Frama-C, the better the chances of analyzing it well, so if such external libraries are not essential, excluding them might help get a more "POSIXy" code, which should help. This is typically visible in config.h files, in macros commonly named HAVE_*.
Compile and install Build EAR or some equivalent tool to obtain a compile_commands.json file.
Run bear make (or cmake with flag CMAKE_EXPORT_COMPILE_COMMANDS) to get the compile_commands.json file.
Run the aforementioned list_files.py in the directory containing compile_commands.json to obtain the list of C sources used during compilation.
Run Frama-C (17 Chlorine or newer), giving it the list of sources found in the previous step, plus option -json-compilation-database . to parse the compile_commands.json and, hopefully, get the appropriate preprocessing flags.
Ideally, this should suffice, but in practice, this is rarely enough. In particular due to the presence of external libraries and non-C99, non-POSIX functions, the following steps are always needed.
6. Inclusion of external libraries
At this step, Frama-C will complain about the lack of event.h. You'll have to include the headers of this library yourself. Note: copying headers directly from your /usr/include is not likely to work, due to several architecture-specific definitions, especially files such as bits/*.h..
Instead, consider downloading the external libraries and preparing them (e.g. running ./configure at least). Then manually add the extra include directory via -cpp-extra-args="-I <path/to/your/sources/for/libevent.h>/include".
7. Inclusion of missing non-POSIX headers
Some other headers may be missing, in particular GNU- or BSD-specific sources (e.g. sysexits.h). Get these headers and add them when necessary. The error message in this case comes from the preprocessor (gcc) and is similar to this:
memcached.c:51:10: fatal error: sysexits.h: No such file or directory
#include <sysexits.h>
^~~~~~~~~~~~
compilation terminated.
8. Definition of missing non-POSIX types and constants
At this point, all necessary headers should be available, but parsing with Frama-C may still fail. This is due to usage of non-POSIX type definitions (e.g. caddr_t, struct ling), non-POSIX constants (e.g. MAXPATHLEN, SOCK_NONBLOCK, NI_MAXSERV). Error messages typically resemble the following:
[kernel] memcached.c:3261: Failure: Cannot resolve variable MAXPATHLEN
Constants are often easy to provide manually, by grepping what's available in your /usr/include.
Type definitions, on the other hand, may require some copy-pasting at the right places, especially if they depend on other types which are also missing. This step is hardly automatizable, but relatively straightforward once you get used to some specific error messages.
For instance, the following error message is related to a missing type definition (caddr_t):
[kernel] Parsing memcached.c (with preprocessing)
[kernel] memcached.c:1074:
syntax error:
Location: line 1074, between columns 38 and 47, before or at token: c
1072 *hdr++ = 0;
1073 *hdr++ = 0;
1074 assert((void *) hdr == (caddr_t)c->msglist[i].msg_iov[0].iov_base + UDP_HEADER_SIZE);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1075 }
1076
Note that the token just before c is (caddr_t), which has never been defined (it is often defined as either void * or char *).
The following error message is related to an incomplete type, i.e., a struct used somewhere but never defined:
[kernel] memcached.c:5811: User Error:
variable `ling' has initializer but incomplete type
It means that variable ling's type, which is struct linger (non-POSIX), has never been defined. In this case, we can copy it from our /usr/include/bits/socket.h:
struct linger
{
int l_onoff; /* Nonzero to linger on close. */
int l_linger; /* Time to linger. */
};
Note: if there are POSIX constants/definitions missing from Frama-C's libc, consider notifying its developers, or proposing pull requests in Frama-C's Github.
9. Fixing incompatible and missing function prototypes
Parsing is likely to succeed after the previous step, but it may still fail due to incompatible function prototypes. For instance, you may get:
[kernel] User Error: Incompatible declaration for usleep:
different integer types int and unsigned int
First declaration was at assoc.c:238
Current declaration is at items.c:1573
This is the consequence of a warning emitted earlier:
[kernel:typing:implicit-function-declaration] slabs.c:1150: Warning:
Calling undeclared function usleep. Old style K&R code?
It means that function usleep is called, but it does not have a prototype, therefore Frama-C uses the pre-C99 convention of "implicit int": it generates such a prototype, but later in the code, an actual declaration of usleep is found, and its type is not int. Hence the error.
To prevent this, you need to ensure usleep's prototype is properly included. Since it is not POSIX.1-2008, you need to either define/undefine the appropriate macros (see unistd.h), or add your own prototype.
At the end, this should allow Frama-C to parse the files and build an AST.
However, there are several missing prototypes yet; we were just lucky that none conflicted with actual declarations. Ideally, you'll consider the parsing stage done when there are no more messages such as implicit-function-declaration and similar warnings.
Some of the missing prototypes in memcached, such as getsubopt, are POSIX and should be integrated into Frama-C's standard library. Others might make part of a small library of non-standard stubs, to be reused for other software.
Contributing with results for future reuse
Successful conclusion of the parsing stage for such open source libraries is enough to consider them for integration into this repository of open source case studies, so that future users can start their analyses without having to redo all of these steps. (The repository is oriented towards Eva, but not exclusively: parsing is useful for all of Frama-C plug-ins.)

`_naked`: Trying to compile legacy 8051 (FX2) code with SDCC, newer version stumbles

I have legacy code for an embedded 8051 core (in a cypress FX2) that used to compile with other versions of SDCC. However, current SDCC doesn't know the _naked qualifier:
delay.c:27: syntax error: token -> '_naked' ; column 21
as triggered by
static void
udelay1 (void) _naked
{
_asm ; lcall that got us here took 4 bus cycles
ret ; 4 bus cycles
_endasm;
}
and other occurrences.
As _naked practically is supposed to tell the C compiler to "nah, ignore the fact that you're a C compiler and understand that you'd need to save frame context", I don't feel like I should just #define it away.
Is there any solution to this? Should I just go ahead and manually inline the assembler wherever a _naked function is used? I feel like I'd betraying the compiler on a CALL there, and that would change the timing.
_naked was replaced by __naked in newer versions of SDCC. Same applies to asm/__asm, at/__at, interrupt,bit,xdata/__….
So, this turned out to be an exercise in regex replacements.
I'm still having linker/ranlib/mostly ar problems, and CMake ignores what I instruct it to use as compilers, but oh well.

GCC declarations: typedef __pid_t pid_t?

I am confused about the declaration of (for example) pid_t. What does __pid_t mean? Is it another type defined elsewhere? If yes, where? Why is my types.h in ubuntu 13.04 64bit defining pid_t like:
#ifndef __pid_t_defined
typedef __pid_t pid_t;
#define __pid_t_defined
#endif
and not something like
typedef int pid_t;
I saw some websites that have types.h headers with the declaration done the last way. This is one:
http://www.sde.cs.titech.ac.jp/~gondow/dwarf2-xml/HTML-rxref/app/gcc-3.3.2/lib/gcc-lib/sparc-sun-solaris2.8/3.3.2/include/sys/types.h.html
UPDATE:
Ok I found out that a pid_t is an __pid_t which is an __PID_T_TYPE which is which is an __S32_TYPE which is an int. My question now is why is this? POSIX only states that pid_t has to be a signed integer, so why make the declaration enter soo deep in header files?
If you are pulling up your types.h via 'man types' then at the top of the header file(under description in the man page) there should exist an include file that defines '__pid_t' at some point as a signed integer(if Ubuntu claims that their types are POSIX compliant; otherwise pid_t could be anything). The symbol ' __' is considered reserved(C standard, dunno about C++). If I had to take a wild guess as to why pid_t is defined as __pid_t and not some int is because __pid_t is what Debian's or the Linux Kernel's developers decided to use for the process ID variable name in all of their library functions; therefore only '__pid_t' needs to be changed to change the integer size for a process ID.
You should really look around before asking a question, similar stackoverflow questions are easily found: Size of pid_t, uid_t, gid_t on Linux .
Ok I found what the __pid_t means on the answer to this question:
Why PID of a process is represented by opaque data type?
QUOTE
typedef __pid_t pid_t;
...
# define __STD_TYPE typedef
__STD_TYPE __PID_T_TYPE __pid_t; /* Type of process identifications. */
...
#define __PID_T_TYPE __S32_TYPE
...
#define __S32_TYPE int
UNQUOTE
So pid_t is an __pid_t which is an __PID_T_TYPE which is which is an __S32_TYPE which is an int.

mingw spitting countless warnings about ignoring "dll import" attribute

I'm using mingw32-make to compile a qt project that uses opengl, it compiles correctly and everything, but it spits countless warning messages of the form:
c:/qt3/include/qcolor.h:67: warning: inline function `int qGray(int, int,
int)' declared as dllimport: attribute ignored
For this particular instance, the function declaration is:
Q_EXPORT inline int qGray( int r, int g, int b )// convert R,G,B to gray 0..255
{ return (r*11+g*16+b*5)/32; }
My question is, why is it spitting all these warning? how can I silence them without silencing other legitimate warnings (i.e. warnings that are related directly to my code and could be potential problems)?
More importantly, why is mingw ignoring the dll import attribute in the first place?
I think Qt ought to only define Q_EXPORT (Q_DECL_EXPORT in Qt 4) to be the dllexport/import attribute if one of the following macros is defined, so make sure your makefiles or code that includes Qt headers (which eventually will include qglobal.h) aren't defining any of them: WIN32, _WIN32, __WIN32__, WIN64, _WIN64, __WIN64__. Or you can just define Q_EXPORT to be nothing in your compile (or preprocessor) flags, then Qt should skip defining it.

Resources