cil-project / cil Goto Github PK
View Code? Open in Web Editor NEWC Intermediate Language
License: Other
C Intermediate Language
License: Other
removed
Currently CIL is defeated by always_inline extern inline functions whose prototypes are repeated after their definition (but before their use).
$ cat vminimal.i
extern void f(void);
extern inline __attribute__((always_inline)) void g()
{
f();
}
extern inline __attribute__((always_inline)) void g();
void v(void)
{
g();
}
$ cc -c -o vminimal.o vminimal.i
$ cilly -c -o vminimal.o vminimal.i
vminimal.i: In function ‘v’:
vminimal.i:2:59: error: inlining failed in call to always_inline ‘g’: function body not available
extern inline __attribute__((always_inline)) void g()
^
vminimal.i:11:3: error: called from here
g();
^
The following patch fixes things for me. (I'll forward it by e-mail too, since GitHub doesn't let me attach it.)
diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml
index dc185e1..30633c6 100644
--- a/src/frontc/cabs2cil.ml
+++ b/src/frontc/cabs2cil.ml
@@ -1792,7 +1792,7 @@ let makeGlobalVarinfo (isadef: bool) (vi: varinfo) : varinfo * bool =
(* New-style extern inline handling: the real definition replaces the extern
inline one *)
- if (not !Cil.oldstyleExternInline) && oldvi.vstorage = Extern && oldvi.vinline then begin
+ if (not !Cil.oldstyleExternInline) && oldvi.vstorage = Extern && oldvi.vinline && isadef then begin
H.remove alreadyDefined oldvi.vname;
theFile := Util.list_map (fun g -> match g with
| GFun (fi, l) when fi.svar == oldvi -> GVarDecl(fi.svar, l)
I am trying to compile Wget-1.14 source code with CIL. I made the default configuration of the Makefile in wget-1.14/lib/Makefile from:
AR = ar
ARFLAGS = cru
CC = gcc
CFLAGS = -g -O2 -Wall -pthread -static
to
AR = cilly --save-temps=build --merge --keepmerged --mode=AR
ARFLAGS = r
CC = cilly --save-temps=build --merge --keepmerged
CFLAGS = -g -O2 -Wall -pthread -static
When the make file is run, to create the library libgnu.a the following command is run as the last step:
cilly --save-temps=build --merge --keepmerged --mode=AR r libgnu.a base32.o c-ctype.o c-strcasecmp.o c-strncasecmp.o cloexec.o md5.o sha1.o dirname-lgpl.o basename-lgpl.o stripslash.o exitfail.o fatal-signal.o fd-hook.o fd-safer-flag.o dup-safer-flag.o gettime.o localcharset.o glthread/lock.o pipe2.o pipe2-safer.o quotearg.o sockets.o spawn-pipe.o stat-time.o tempname.o glthread/threadlib.o timespec.o tmpdir.o dup-safer.o fd-safer.o pipe-safer.o utimens.o wait-process.o xmalloc.o xalloc-die.o asnprintf.o fcntl.o futimens.o getpass.o ioctl.o printf-args.o printf-parse.o strerror_r.o vasnprintf.o
On running this command, the following error is thrown at line 258 of md5.c:
Library libgnu.a not found; creating. at *******
Turning off warn-is-error flag
***/cil/obj/x86_LINUX/cilly.asm.exe --extrafiles ___extra_files --mergedout libgnu.a
md5.c[258:0-0] : syntax error
Parsing errorFatal error: exception Frontc.ParseError("Parse error")
Makefile:1383: recipe for target 'libgnu.a' failed
make[2]: *** [libgnu.a] Error 2
The code for md5.c from line 258 is in function md5_process_bytes. Lines 253-273 looks like:
253 /* Process available complete blocks. */
254 if (len >= 64)
255 {
256 #if !_STRING_ARCH_unaligned
257 # define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (uint32_t) != 0)
258 if (UNALIGNED_P (buffer)){
259 while (len > 64)
260 {
261 md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
262 buffer = (const char *) buffer + 64;
263 len -= 64;
264 }
265 }
266 else
267 #endif
268 {
269 md5_process_block (buffer, len & ~63, ctx);
270 buffer = (const char *) buffer + (len & ~63);
271 len &= 63;
272 }
273 }
I hope if anyone can share your opinions and suggestions on the potential syntactical error that CIL might be encountering.
Thanks in advance.
CIL gives names to anonymous structure or union types, such as in the following.
typedef struct { double r; double i; } complex;
CIL will give it a name such as __anonstruct_complex_nn, where 'nn' is a number chosen serially. So, the same header defining the same struct complex will generate different 'nn' in different compilation units, because of the different inclusion contexts.
This is harmless in nearly all applications of CIL. But in my case it causes a problem, because according to the C standard, types with different tags are not compatible (section 6.2.7), whereas before the CIL transformation, they were compatible. It's important for my tool that compatibility across compilation units is preserved; I therefore have to erase the 'nn' to work around this behaviour.
A better option for CIL would be to compute the nn based on a structural analysis of the definition, so that the same nn would always be generated for the "same" struct. This would not be easy to get completely right, but a "good enough" version probably isn't too hard. Consider that an offer to contribute a patch at some point!
I want to simply print out a callgraph while using cil.callgraph as followed:
open Cil module E = Errormsg module L = List module CG = Callgraph let test f:file = let cg= CG.computeGraph f in CG.printGraph stdout cg (*merge the input file e.t.c.*)
however as I was using
ocamlfind ocamlc -linkpkg -thread -package cil,cil.callgraph test.ml -o test.byte
File "test.ml", line 1: Error: Error while linking /home/lcm/.opam/system/lib/cil/cil.cma(Feature): Reference to undefined global `Findlib'
I do not know where to start debugging with
Does anyone have any idea?
I have installed cil-1.7.2 via opam-1.0.0 and have the following error when I tried to compile a package with CIL.
gcc: error: /ocamlbrew/ocaml-4.00.1/.opam/system/lib/cil/cil.a: No such file or directory
File "caml_startup", line 1:
Error: Error during linking
Syntactic search returns no results (not when querying through GobView, but also not when querying through Goblint directly).
Steps to reproduce the issue:
Run the Goblint-http server:
./_build/default/gobview/goblint-http-server/goblint_http.exe -with-goblint ../analyzer/goblint -goblint --set save_run run -v --set files[+] "../analyzer/tests/regression/00-sanity/01-assert.c"
Open the web UI. Scroll down until you see "Switch to JSON editor" and click it. Enter the following query and click "Execute":
{"kind":["var"],"target":["name","fail"],"find":["uses"],"expression":"","mode":["Must"]}
If you allow for non-semantic queries in the expression evaluator (expressionEvaluation.ml) in Goblint1 the query can also directly be handed to Goblint. Save the same query in a file (e.g., query.json) and execute the syntactic search in the terminal like this:
./goblint --set trans.activated[+] expeval -v --set trans.expeval.query_file_name query.json tests/regression/00-sanity/01-assert.c
This also does not return any result.
This can for example be quickly hacked by changing
https://github.com/goblint/analyzer/blob/5464235e9cc77156746da5f25d336f9d9dac0d1e/src/transform/expressionEvaluation.ml#L195
to
|> (fun ls -> if query.expression != "" then List.map (fun (n, l, s, i) -> ((n, l, s, i), evaluator#evaluate l query.expression)) ls else List.map (fun a -> (a, None)) ls)
↩
Trace is a bad choice of name for a module inside CIL. It prevents the OCAML toplevel from linking.
ocamlmktop -o cilmain -I ocamlfind -query cil
nums.cma unix.cma str.cma cil.cma cilmain.cmo
File "/home/jrrk2/.opam/4.03.0/lib/cil/cil.cma(Trace)", line 1:
Warning 31: files /home/jrrk2/.opam/4.03.0/lib/cil/cil.cma(Trace) and
/home/jrrk2/.opam/4.03.0/lib/ocaml/compiler-libs/ocamltoplevel.cma(Trace) both define a module named Trace
Error: Some fatal warnings were triggered (1 occurrences)
Newer gcc option that CIL doesn't seem to be aware of.
Commenting that out, it still fails on #12.
Are there plans to continue development on CIL or has the CIL repo moved elsewhere? It looks like the last update was around a year ago.
Thanks!
We are currently studying the usage of GCC builtins by GitHub projects and how well various tools support them. To that end, we are also developing a test suite for the most frequently used machine-independent GCC builtins (available at https://github.com/gcc-builtins/tests). We'd be glad to contribute the test suite (or parts of it) to cil, if you are interested.
Out of the currently 100 builtin tests, cilly passes 40. The builtins __builtin_bswap16
and __builtin_types_compatible_p
seem to be supported, but produce incorrect results, as the test cases below demonstrate:
#include <assert.h>
#include <stdint.h>
int main() {
volatile uint16_t value = -1;
assert(__builtin_bswap16(value) == (uint16_t)-1);
return 0;
}
#include <assert.h>
int main() {
assert(!__builtin_types_compatible_p(enum {foo, bar}, enum {hot, dog}));
}
The second test case is derived from an example given by the GCC docs, which state:
An enum type is not considered to be compatible with another enum type even if both are compatible with the same integer type; this is what the C standard specifies. For example, enum {foo, bar} is not similar to enum {hot, dog}.
From the other failing test cases, 4 are due to warnings about long double values being treated as doubles, for example, in 68-__builtin_fabs.c
:
treating long double constant 1.79769313486231570814527423731704357e+308L as double constant at test-cases/68-__builtin_fabs.c:11.
15 failures are caused by parsing errors of a header file, for example, included in 2-__builtin_islessequal.c
:
/usr/include/x86_64-linux-gnu/bits/mathcalls-helper-functions.h[21:12-28] : syntax error
Parsing errorFatal error: exception Frontc.ParseError("Parse error")
Execution of 34 test cases failed by having received signal 11
, for example, in 89-__atomic_compare_exchange.c
. These failures seem to affect only atomic builtins.
The remaining 5 failures are due to unrecognized builtins, for example, in 57-__builtin_add_overflow.c
:
cil-z7uEm65O.cil.c:(.text+0x3b): undefined reference to `__builtin_add_overflow'
gcc 4.3 added a new intrinsic, __builtin_bswap32. Currently CIL doesn't know about this builtin, so will emit a (wrongly-typed) prototype for it, causing undefined references in the output object file. The following patch fixes the problem for me.
diff --git a/src/cil.ml b/src/cil.ml
index 1c737e8..343216f 100644
--- a/src/cil.ml
+++ b/src/cil.ml
@@ -2835,6 +2835,7 @@ let initGccBuiltins () : unit =
(* See if we have builtin_va_list *)
let hasbva = !M.theMachine.M.__builtin_va_list in
let ulongLongType = TInt(IULongLong, []) in
+ let uIntType = TInt(IUInt, []) in
let floatType = TFloat(FFloat, []) in
let longDoubleType = TFloat (FLongDouble, []) in
let voidConstPtrType = TPtr(TVoid [Attr ("const", [])], []) in
@@ -2878,6 +2879,8 @@ let initGccBuiltins () : unit =
H.add h "__builtin_atan2l" (longDoubleType, [ longDoubleType;
longDoubleType ], false);
+ H.add h "__builtin_bswap32" (uIntType, [ uIntType ], false);
+
H.add h "__builtin_ceil" (doubleType, [ doubleType ], false);
H.add h "__builtin_ceilf" (floatType, [ floatType ], false);
H.add h "__builtin_ceill" (longDoubleType, [ longDoubleType ], false);
As title.
To deal with a build system that wants to run the compiler with "-DSHA1_HEADER=<path/to/blah>" I had to apply the following patch to cilly.
diff --git a/lib/Cilly.pm.in b/lib/Cilly.pm.in
index 3ec40a8..8d1943b 100644
--- a/lib/Cilly.pm.in
+++ b/lib/Cilly.pm.in
@@ -1219,9 +1219,6 @@ sub compilerArgument {
&{$action->{'RUN'}}($self, @fullarg, $onemore, $pargs);
$argument_done = 1;
}
- # Quote special SHELL caracters
- @fullarg = map { $_ =~ s%([<>;&|])%'$1'%g; $_ } @fullarg;
- # print "fullarg = ", @fullarg, "\n";
if(defined $action->{'TYPE'}) {
&classifyArgDebug(" type=$action->{TYPE}\n");
if($action->{TYPE} eq 'EARLY_PREPROC') {
Without this, the compiler was getting a string in its argv that contained literal quotes. To me, it doesn't look like the quoting is necessary at all, but I might be missing something.
When trying to install CIL's develop branch using ./configure --prefix=/path, make install fails because it is trying to install into /usr. ./configure --help suggests to use --prefix to install to a different location. It seems there's some ocamlfind magic in the Makefile.in that breaks this
Hi, when I tried to install the cil in my ubuntu 18.04.4 TLS, I found some problems.
First, I tried to use
opam install cil
to install cil but it shows
[ERROR] cil is not a valid versioned package name
'opam install cil' failed.
After that, I tried opam install cil.1.7.3
but it still couldn't work.
[ERROR] "cil" is not a valid package.
'opam install cil.1.7.3' failed.
Then I tried to use the project to make it.
But after I run ./configure successfully, when I run make
, some error occured.
......
/usr/bin/ld: /usr/lib/ocaml/libasmrun.a(compact.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: /usr/lib/ocaml/libasmrun.a(finalise.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: /usr/lib/ocaml/libasmrun.a(custom.o): relocation R_X86_64_32S against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: /usr/lib/ocaml/libasmrun.a(unix.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: /usr/lib/ocaml/libasmrun.a(backtrace.o): relocation R_X86_64_32 against symbol `caml_backtrace_last_exn' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking
Command exited with code 2.
Makefile:102: recipe for target 'ocamlbuild' failed
make[1]: *** [ocamlbuild] Error 10
make[1]: Leaving directory '/home/zby/Downloads/cil'
Makefile:371: recipe for target 'install-local' failed
make: *** [install-local] Error 2
cilly assumes that source files have names with meaningful extensions. In the case of the source file "-", denoting stdin, this doesn't work.
$ gcc hello.c -S -o hello.s # works okay
$ file hello.s; rm -f hello.s
hello.s: assembler source text
$ cilly hello.c -S -o hello.s # works okay
$ file hello.s; rm -f hello.s
hello.s: assembler source text
$ cat hello.c | gcc -x c - -S -o hello.s # works okay
$ file hello.s; rm -f hello.s
hello.s assembler source text
$ cat hello.c | cilly -x c - -S -o hello.s # BUG!
$ file hello.s
hello.s: ERROR: cannot open `hello.s' (No such file or directory)
A related problem is that cilly doesn't correctly handle gcc's "-x " option, which is often used in combination with input on stdin. Currently cilly just passes this options to the compiler --
which sometimes works, but doesn't preserve the option's semantics. For example,
$ gcc -E -o hello.cc hello.c
$ gcc -x cpp-output -o hello hello.cc
... works, whereas
$ cilly -E -o hello.cc hello.c
$ cilly -x cpp-output -o hello hello.cc
(snip)
/tmp/cil-jSfqyHOy.o:6:4: error: stray ?\2? in program
/tmp/cil-jSfqyHOy.o:6:21: warning: null character(s) ignored
/tmp/cil-jSfqyHOy.o:6:4: error: stray ?\2? in program
/tmp/cil-jSfqyHOy.o:6:25: warning: null character(s) ignored
I have prepared a rough patch with fixes both of these problems. It's not great code (my Perl is amateurish) and could use a quick review. (Am happy to submit by e-mail, and/or rework any part that could do with a better solution.)
diff --git a/lib/perl5/App/Cilly.pm.in b/lib/perl5/App/Cilly.pm.in
index 63f9163..6e48d1f 100644
--- a/lib/perl5/App/Cilly.pm.in
+++ b/lib/perl5/App/Cilly.pm.in
@@ -199,7 +199,7 @@ sub collectArgumentList {
#
# my $arg = shift @args; # Grab the next one
if(! $self->collectOneArgument($arg, \@args)) {
- print "Warning: Unknown argument $arg\n";
+ if (! $arg eq "-") { print STDERR "Warning: Unknown argument $arg\n"; }
push @{$self->{CCARGS}}, $arg;
}
}
@@ -541,25 +541,38 @@ sub preprocess_compile {
&mydebug("preprocess_compile(src=$src, dest=$dest)\n");
Carp::confess "bad dest: $dest" unless $dest->isa('App::Cilly::OutputFile');
- my ($base, $dir, $ext) = fileparse($src, "\\.[^.]+");
- if($ext eq ".c" || $ext eq ".cpp" || $ext eq ".cc") {
- if($self->leaveAlone($src)) {
- print "Leaving alone $src\n";
- # We leave this alone. So just compile as usual
- return $self->straight_compile($src, $dest, [@{$early_ppargs}, @{$ppargs}], $ccargs);
- }
- my $out = $self->preprocessOutputFile($src);
- $out = $self->preprocess($src, $out,
- [@{$early_ppargs}, @{$ppargs},
- "$self->{DEFARG}CIL=1"]);
- return $self->compile($out, $dest, $ppargs, $ccargs);
+ if (! $src eq "-") {
+ my ($base, $dir, $ext) = fileparse($src, "\\.[^.]+");
+ # check that they're sane
+ die "preprocess_compile requires an unpreprocessed source file! got $src\n"
+ unless ($ext eq ".c" || $ext eq ".cpp" || $ext eq ".cc");
}
- if($ext eq ".i") {
- return $self->compile($src, $dest, $ppargs, $ccargs);
+
+ if($self->leaveAlone($src)) {
+ print "Leaving alone $src\n";
+ # We leave this alone. So just compile as usual
+ return $self->straight_compile($src, $dest, [@{$early_ppargs}, @{$ppargs}], $ccargs);
}
- if($ext eq ".$::cilbin") {
- return $self->compile($src, $dest, $ppargs, $ccargs);
+ my $out = $self->preprocessOutputFile($src);
+ $out = $self->preprocess($src, $out,
+ [@{$early_ppargs}, @{$ppargs},
+ "$self->{DEFARG}CIL=1"]);
+ return $self->compile($out, $dest, $ppargs, $ccargs);
+}
+
+sub compile_nopp {
+ my ($self, $src, $dest, $early_ppargs, $ppargs, $ccargs) = @_;
+ &mydebug("compile_nopp(src=$src, dest=$dest)\n");
+ Carp::confess "bad dest: $dest" unless $dest->isa('App::Cilly::OutputFile');
+
+ if (! $src eq "-") {
+ my ($base, $dir, $ext) = fileparse($src, "\\.[^.]+");
+ # check that they're sane
+ die "compile_nopp requires a preprocessed source file! got $src\n"
+ unless ($ext eq ".i" || $ext eq ".$::cilbin");
}
+
+ return $self->compile($src, $dest, $ppargs, $ccargs);
}
# THIS IS THE ENTRY POINT FOR JUST PREPROCESSING A FILE
@@ -1095,8 +1108,8 @@ sub doit {
# we can go ahead with the compilation, without having to save
# files
if(! $self->{SEPARATE} && # Not already separate mode
- $self->{OPERATION} eq "TOEXE" && # We are linking to an executable
- @{$self->{CFILES}} + @{$self->{IFILES}} <= 1) { # At most one source
+ @{$self->{CFILES}} + @{$self->{IFILES}} <= 1 && # At most one source
+ ($self->{OPERATION} eq "TOEXE" || defined $self->{OUTARG})) { # We are linking to an executable
# If we have object files, we should keep merging if at least one
# object file is a disguised source
my $turnOffMerging = 0;
@@ -1117,16 +1130,22 @@ sub doit {
}
}
- # Turn everything into OBJ files
+ # Turn everything into OBJ files (or assembly, if the user asked for that)
my @tolink = ();
-
- foreach $file (@{$self->{IFILES}}, @{$self->{CFILES}}) {
+ foreach $file (@{$self->{CFILES}}) {
$out = $self->compileOutputFile($file);
$self->preprocess_compile($file, $out,
$self->{EARLY_PPARGS},
$self->{PPARGS}, $self->{CCARGS});
push @tolink, $out;
}
+ foreach $file (@{$self->{IFILES}}) {
+ $out = $self->compileOutputFile($file);
+ $self->compile_nopp($file, $out,
+ $self->{EARLY_PPARGS},
+ $self->{PPARGS}, $self->{CCARGS});
+ push @tolink, $out;
+ }
# Now do the assembly language file
foreach $file (@{$self->{SFILES}}) {
$out = $self->assembleOutputFile($file);
@@ -1184,23 +1203,25 @@ sub doit {
}
sub classifyArgDebug {
- if(0) { print @_; }
+ if(1) { print @_; }
}
sub mydebug {
- if(0) { print @_; }
+ if(1) { print @_; }
}
sub compilerArgument {
my($self, $options, $arg, $pargs) = @_;
&classifyArgDebug("Classifying arg: $arg\n");
my $idx = 0;
+ my $matched = 0;
for($idx=0; $idx < $#$options; $idx += 2) {
my $key = ${$options}[$idx];
my $action = ${$options}[$idx + 1];
&classifyArgDebug("Try match with $key\n");
if($arg =~ m|^$key|) {
&classifyArgDebug(" match with $key\n");
+ $matched = 1;
my @fullarg = ($arg);
my $onemore;
if(defined $action->{'ONEMORE'}) {
@@ -1218,6 +1239,21 @@ sub compilerArgument {
}
&classifyArgDebug(" onemore=$onemore\n");
}
+ # If we have CURLANG, it might override the action the caller
+ # supplied.
+ if (defined $self->{'CURLANG'}) {
+ if ($action->{TYPE} =~ /.*SOURCE$/) {
+ if ($self->{CURLANG} =~ /c|c-header/) { $action->{TYPE} = "CSOURCE"; }
+ elsif ($self->{CURLANG} =~ /cpp-output/) { $action->{TYPE} = "ISOURCE"; }
+ elsif ($self->{CURLANG} =~ /assembler/) { $action->{TYPE} = "ASMSOURCE"; }
+ elsif ($self->{CURLANG} =~ /assembler-woth-cpp/) { $action->{TYPE} = "ASMSOURCE"; }
+ else {
+ print "Warning: didn't understand current language $self->{CURLANG}\n";
+ }
+ }
+ } elsif ($action->{TYPE} eq "UNKNOWNSOURCE") {
+ print "Warning: saw source of unknown language, with no preceding -x <lang>\n";
+ }
# Now see what action we must perform
my $argument_done = 1;
if(defined $action->{'RUN'}) {
@@ -1240,7 +1276,17 @@ sub compilerArgument {
elsif($action->{TYPE} eq "CC") {
push @{$self->{CCARGS}}, @fullarg; return 1;
}
- elsif($action->{TYPE} eq "LINKCC") {
+ elsif($action->{TYPE} eq "SETLANG") {
+ # We pass it to the C compiler, as if it were a "CC" action,
+ # but we also keep some state so we can classify input files.
+ if ($onemore eq "none") {
+ delete $self->{CURLANG};
+ } else {
+ $self->{CURLANG} = $onemore;
+ }
+ push @{$self->{CCARGS}}, @fullarg; return 1;
+ }
+ elsif($action->{TYPE} eq "LINKCC") {
push @{$self->{CCARGS}}, @fullarg;
push @{$self->{LINKARGS}}, @fullarg; return 1;
}
@@ -1255,6 +1301,7 @@ sub compilerArgument {
elsif($action->{TYPE} eq "CSOURCE") {
App::Cilly::OutputFile->protect(@fullarg);
$fullarg[0] = &normalizeFileName($fullarg[0]);
+ print "Pushing $fullarg[0]\n";
push @{$self->{CFILES}}, @fullarg; return 1;
}
elsif($action->{TYPE} eq "ASMSOURCE") {
@@ -1285,6 +1332,7 @@ sub compilerArgument {
print "Don't know what to do with option $arg\n";
return 0;
}
+
}
return 0;
}
@@ -1924,6 +1972,7 @@ sub new {
"[^-].*\\.($::cilbin|c|cpp|cc)\$" => { TYPE => 'CSOURCE' },
"[^-].*\\.(s|S)\$" => { TYPE => 'ASMSOURCE' },
"[^-].*\\.i\$" => { TYPE => 'ISOURCE' },
+ "-\$" => { TYPE => 'UNKNOWNSOURCE' },
# .o files can be linker scripts
"[^-]" => { RUN => sub { &GNUCC::parseLinkerScript(@_); }},
@@ -1935,7 +1984,7 @@ sub new {
"-o" => { ONEMORE => 1, TYPE => 'OUT' },
"-combine\$" => { TYPE => 'ALLARGS' },
"-pipe\$" => { TYPE => 'ALLARGS' },
- "-x" => { ONEMORE => 1, TYPE => "CC" },
+ "-x" => { ONEMORE => 1, TYPE => "SETLANG" },
"-v" => { TYPE => 'ALLARGS',
RUN => sub { $stub->{TRACE_COMMANDS} = 1; } },
# skipping -###, --help, --target-help, --version
@@ -2176,8 +2225,11 @@ sub lineDirective {
sub compileOutputFile {
my($self, $src) = @_;
- die "objectOutputFile: not a C source file: $src\n"
- unless $src =~ /\.($::cilbin|c|cc|cpp|i|s|S)$/;
+ # in the "-" case we will have an OUTARG
+ if ($src eq "-") { die "input is '-' but no outarg\n" unless defined $self->{OUTARG}; }
+ else { die "objectOutputFile: not a C source file: $src\n"
+ unless $src =~ /\.($::cilbin|c|cc|cpp|i|asm)$/;
+ }
if ($self->{OPERATION} eq 'TOOBJ'
|| ($self->{OPERATION} eq 'TOASM')) {
git clone https://github.com/cil-project/cil
cd cil
./configure
make
results in
+ ocamlfind ocamlc -c -I src -I src/ocamlutil -I src/frontc -I src/ext -I src/ext/zrapp -I src/ext/simplify -I src/ext/simplemem -I src/ext/sfi -I src/ext/pta -I src/ext/partial -I src/ext/oneret -I src/ext/logwrites -I src/ext/logcalls -I src/ext/llvm -I src/ext/liveness -I src/ext/inliner -I src/ext/heapify -I src/ext/epicenter -I src/ext/dataslicing -I src/ext/cqualann -I src/ext/ccl -I src/ext/canonicalize -I src/ext/callgraph -I src/ext/blockinggraph -o src/cilint.cmi src/cilint.mli
File "src/cilint.mli", line 6, characters 36-51:
6 | type cilint = Small of int | Big of Big_int.big_int
^^^^^^^^^^^^^^^
Error: Unbound module Big_int
Command exited with code 2.
make[1]: *** [Makefile:103: ocamlbuild] Error 10
make[1]: Leaving directory '/home/sam/Downloads/test2/test/cil'
make: *** [Makefile:371: install-local] Error 2
See also jburnim/crest#20
It would be nice to have an opam package for OCaml >= 4.02, since the current one leads to segmentation faults (and cilly doesn't terminate).
Also, for the develop-branch, I had to add package(cil.all-features)
to my _tags
file, which isn't available using the opam package. Could we make that compatible somehow?
Using cilly to compile eglibc 2.19 fails at configure time, complaining:
configure:6792: error: support for the symbol redirection needed
The failing test program (conftest.c) looks like this:
extern char *strstr (const char *, const char *) __asm ("my_strstr");
char *foo (const char *a, const char *b)
{
return __builtin_strstr (a, b);
}
The configure script expects to see a reference to my_strstr in the output assembly. This holds for gcc, but not for cilly wrapping gcc.
After fixing a trivial earlier bug (that __builtin_strstr was not included in the builtins list; patch sent!), we get
/* Generated by CIL v. 1.7.3 */
/* print_CIL_Input is true */
/* compiler builtin:
char *__builtin_strstr(char const * , char const * ) ; */
#line 2 "conftest.c"
char *foo(char const *a , char const *b )
{
char *tmp ;
{
#line 4
tmp = __builtin_strstr(a, b);
#line 4
return (tmp);
}
}
where we note that our prototype for strstr has gone away! That's because it appears to be unused. My proposed fix is a gross hack to rmtmps, something like as follows, but I'd be amenable to cleaner suggestions.
diff --git a/src/rmtmps.ml b/src/rmtmps.ml
index 2034623..09b5bde 100644
--- a/src/rmtmps.ml
+++ b/src/rmtmps.ml
@@ -422,6 +422,21 @@ class markReachableVisitor
| GVarDecl (varinfo, _)
| GFun ({svar = varinfo}, _) ->
varinfo.vreferenced <- true;
+ (* If we're a builtin, but we've seen a prototype for the
+ * corresponding non-builtin function, then mark that one
+ * used too. *)
+ let isBuiltin = H.mem builtinFunctions varinfo.vname in
+ if isBuiltin then begin
+ let nonBuiltinName = Str.replace_first (Str.regexp "^__builtin_") "" varinfo.
+ try
+ let gv = H.find globalMap nonBuiltinName in
+ match gv with
+ GFun({svar = nbvarinfo}, _) -> nbvarinfo.vreferenced <- true; ()
+ | GVarDecl(nbvarinfo, _) -> nbvarinfo.vreferenced <- true; ()
+ | _ -> ()
+ with Not_found -> ()
+ end
+ ;
DoChildren
| _ ->
SkipChildren
With gcc 7:
$ gcc -dumpversion
7
The attached patch fixed it for me.
See my fix at wh5a@0edc631
I'm trying to pass down some information from a C source file prior to the file being preprocessed. I decide to use the #pragma syntax to achieve this
(Unfortunately), there are some constructs which result in a ParseError. For example:
#pragma __test__("blah")
void my_fn_defn(void *ptr)
#pragma __test__("foo")
{
...
}
Why does this fail, isn't the pragma still at the "toplevel"? I.e The scope of the function hasn't started yet.
I recently stumbled on the following code in cabs2cil that handles (non-variadic) function aliases.
let rt, formals, isva, _ = splitFunctionType vtype in
if isva then E.s (error "%a: alias unsupported with varargs."
d_loc !currentLoc);
let args = Util.list_map
(fun (n,_,_) -> A.VARIABLE n)
(argsToList formals) in
let call = A.CALL (A.VARIABLE othername, args) in
let stmt = if isVoidType rt then A.COMPUTATION(call, loc)
else A.RETURN(call, loc)
in
let body = { A.blabels = []; A.battrs = []; A.bstmts = [stmt] } in
let fdef = A.FUNDEF (sname, body, loc, loc) in
ignore (doDecl true fdef);
(* get the new function *)
let v,_ = try lookupGlobalVar thisname
with Not_found -> E.s (bug "error in doDecl") in
v.vattr <- dropAttribute "alias" v.vattr
It seems to define the alias by creating a fresh function which calls the aliased function. This is semantically wrong because the two functions' addresses should be equal. Also, it doesn't handle varargs functions, and aliases of variables are not implemented at all. (I am currently trying to compile eglibc with CIL, and it uses aliases a lot.)
The only sane fix seems to be to change the data model, so that every GVar has a list of aliases, each with their own attributes. This would seem to require an API-breaking change -- or is there a better way?
At least the following would then have to happen. Aliases all get declared when the global is declared. Lookups by name must resolve aliases when appropriate. Each alias probably ought to have its own location, although that could probably be finessed away if it were too great a change.
I am adding this to my internal to-do queue, but would welcome suggestions for alternative ways to deal with it.
Please consider the following patch for inclusion:
Index: myocamlbuild.ml
--- myocamlbuild.ml.orig
+++ myocamlbuild.ml
@@ -21,22 +21,25 @@ let cil_version =
with Not_found -> "" ;;
dispatch begin function
+| Before_options ->
+ Options.use_ocamlfind := true
| After_rules ->
(* the main CIL library *)
ocaml_lib "src/cil";
(* residual reliance on make to build some OCaml source files *)
let make target =
+ let make = try Sys.getenv "MAKE" with Not_found -> "make" in
let basename = Pathname.basename target in
rule ("make " ^ target)
~dep: "Makefile"
~prod: basename
(fun _ _ -> Cmd (S
- [A "make"; A "-C"; P ".."; P ("_build" / target)]))
- in
- make "cilversion.ml";
- make "feature_config.ml";
- make "machdep.ml";
+ [A make; A "-C"; P ".."; P ("_build" / target)]))
+ in
+ make "cilversion.ml";
+ make "feature_config.ml";
+ make "machdep.ml";
(* Build an list of files to install with ocamlfind *)
rule "%.mllib -> %.libfiles"
New gcc extension: http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
I faced this error when trying to use cilly
on Linux with gcc 8
, didn't find much related to this issue from Google, but finally was able to fix the prob. So just want to put the solution here just in case others face the same issue.
The problem seems to be that cilly
doesn't like gcc 8
, so telling cilly
to use an older gcc version works.
$ cilly --merge -c ~/Dropbox/git/WSymtraces/symtracesOld/programs/nla/cohendiv.c
Cannot find GNUCC version
debian Fri Apr 12:21:43:15 (2261) /home/SHARED/Devel/CIL/cil-1.7.3
$ cilly --gcc=/usr/bin/gcc-8 --merge -c ~/Dropbox/git/WSymtraces/symtracesOld/programs/nla/cohendiv.c
Cannot find GNUCC version
debian Fri Apr 12:21:43:22 (2262) /home/SHARED/Devel/CIL/cil-1.7.3
$ cilly --gcc=/usr/bin/gcc-6 --merge -c ~/Dropbox/git/WSymtraces/symtracesOld/programs/nla/cohendiv.c
/usr/bin/gcc-6 -D_GNUCC -E -DCIL=1 /home/tnguyen/Dropbox/git/WSymtraces/symtracesOld/programs/nla/cohendiv.c -o /tmp/cil-HIhbdf4L.i
debian Fri Apr 12:21:43:30 (2263) /home/SHARED/Devel/CIL/cil-1.7.3
$ cilly --gcc=/usr/bin/gcc-4.9 --merge -c ~/Dropbox/git/WSymtraces/symtracesOld/programs/nla/cohendiv.c
/usr/bin/gcc-4.9 -D_GNUCC -E -DCIL=1 /home/tnguyen/Dropbox/git/WSymtraces/symtracesOld/programs/nla/cohendiv.c -o /tmp/cil-fuo0RgEZ.i
debian Fri Apr 12:21:43:34 (2264) /home/SHARED/Devel/CIL/cil-1.7.3
CIL typsigs do not distinguish between the types
typedef int f();
and
typedef int f(void);
I will call the first case "no arguments specified" and the second "specified as no-arguments". They both yield the typesigs
TSFun(TSBase(void ), [],false, [])
Note that Cil.typ does encode this distinction, since the argument list can be Some([]) or None.
A possible fix which doesn't break absolutely everybody's code might be to take the C++ approach: the "no arguments specified" case is encoded as a zero-arguments varargs function, i.e.
TSFun(TSBase(void ), [], true, [])
whereas the "specified as no-arguments" case remains as-is.
I could be persuaded to work on a patch to fix this, although I am just working around it for now. :-)
README.md says:
Read the excellent CIL tutorial by Zachary Anderson
but the CIL tutorial link:
https://bitbucket.org/zanderso/cil-template/downloads/ciltut.pdf
leads to a page saying:
Repository not found
You may not have access to this repository or it no longer exists in this workspace.
I have the error :
Error: Initializing non-constant-length array
with the following C code :
typedef enum
{
A = 0,
B = 1
} Enum;
int main (){
char arr[((Enum)1)] = "a";
printf("%s\n",arr);
}
The code above compiles and runs correctly using GCC.
I'm trying to print gcc function attributes i.e section.
Running this code on function declarations with attribute((section)) fails to produce any output. Any idea?
open Cil
open Pervasives
let print_attr func =
match func with
| GFun(f, _) -> (
(*Printf.printf "%s\n" f.svar.vname;*)
match f.svar.vtype with
| TFun(rt,_,_,attr) ->
ignore(d_attrlist () (typeAttrs rt)); ()
| _ -> ()
)
| _ -> ()
let () =
let cil_file = Frontc.parse "srcfile" () in
iterGlobals cil_file print_attr;
The docs for copyFunction
do not specify what is the behavior of this function when computeCFGInfo
has been called on the given fundec
. I have preemptively looked into copyFunction
's definition and it seems that this case is not handled, vstmt
does not touch succs
nor preds
. This could break the stated invariant that
There should be no sharing between the copy and the original function
The fix should be relatively easy, we need to patch the succs
and preds
fields of each statement in a similar way as it is done for goto
and switch
. Something like
stmtmap |> IH.iter (fun _ s ->
s.succs <- List.map (fun s1 -> findStmt !s1.sid) s.succs;
s.preds <- List.map (fun s1 -> findStmt !s1.sid) s.preds
)
Should I?
Warning: I have not yet tried to copy a fundec
after computing CFG info. I report this issue based on my sole understanding of the code.
Thanks!
The latest version available in opam is 1.5.1.
It would be nice to have a more recent version in opam.
I forked opam-repository and tried to add versions 1.6.0 and 1.7.0 based on 1.5.1.
For 1.6.0 the library seems to work, but executing cilly
fails with Can't locate CilConfig.pm
.
For 1.7.0 I'm stuck at make install
which tries to install something to /usr/local/bin
.
Can it be configured to install to the opam directory? Also, I don't know what to do with the dependency on perl-ExtUtils-MakeMaker.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.