From d5013fc04c672331eeaee0ee1737157c9acdab0e Mon Sep 17 00:00:00 2001
From: Kostyantyn Vorobyov <kostyantyn.vorobyov@cea.fr>
Date: Mon, 15 May 2017 15:27:37 +0200
Subject: [PATCH] Initialize program arguments from within RTL

---
 .../bittree_model/e_acsl_bittree_mmodel.c     | 35 ++++++++++++++-----
 .../segment_model/e_acsl_segment_mmodel.c     | 34 +++++++++++++++++-
 .../segment_model/e_acsl_segment_tracking.h   | 15 --------
 .../tests/runtime/oracle/gen_bypassed_var.c   |  1 -
 .../tests/runtime/oracle/gen_mainargs.c       |  2 --
 src/plugins/e-acsl/visit.ml                   |  6 ++--
 6 files changed, 63 insertions(+), 30 deletions(-)

diff --git a/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c
index 2dfec7bee2c..56ea8d22c63 100644
--- a/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c
+++ b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c
@@ -516,16 +516,33 @@ static void memory_clean() {
   bt_clean();
 }
 
-/* add `argv` to the memory model */
-static void init_argv(int argc, char **argv) {
-  int i;
+extern char **environ;
 
-  store_block(argv, (argc+1)*sizeof(char*));
-  full_init(argv);
+/* add `argv` to the memory model */
+static void argv_alloca(int *argc_ref,  char *** argv_ref) {
+  /* Track a top-level containers */
+  store_block((void*)argc_ref, sizeof(int));
+  store_block((void*)argv_ref, sizeof(char**));
+  int argc = *argc_ref;
+  char** argv = *argv_ref;
+  /* Track argv */
+
+  size_t argvlen = (argc + 1)*sizeof(char*);
+  store_block(argv, argvlen);
+  initialize(argv, (argc + 1)*sizeof(char*));
+
+  while (*argv) {
+    size_t arglen = strlen(*argv) + 1;
+    store_block(*argv, arglen);
+    initialize(*argv, arglen);
+    argv++;
+  }
 
-  for (i = 0; i < argc; i++) {
-    store_block(argv[i], strlen(argv[i])+1);
-    full_init(argv[i]);
+  while (*environ) {
+    size_t envlen = strlen(*environ) + 1;
+    store_block(*environ, envlen);
+    initialize(*environ, envlen);
+    environ++;
   }
 }
 
@@ -535,7 +552,7 @@ static void memory_init(int *argc_ref, char ***argv_ref, size_t ptr_size) {
   initialize_report_file(argc_ref, argv_ref);
   /* Tracking program arguments */
   if (argc_ref)
-    init_argv(*argc_ref, *argv_ref);
+    argv_alloca(argc_ref, argv_ref);
   /* Tracking safe locations */
   collect_safe_locations();
   int i;
diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
index a4002694bf5..9be817a176a 100644
--- a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
+++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
@@ -128,6 +128,38 @@ static size_t get_heap_allocation_size(void) {
 }
 /* }}} */
 
+/* Track program arguments (ARGC/ARGV) {{{ */
+extern char ** environ;
+
+static void argv_alloca(int *argc_ref,  char *** argv_ref) {
+  /* Track a top-level containers */
+  shadow_alloca((void*)argc_ref, sizeof(int));
+  shadow_alloca((void*)argv_ref, sizeof(char**));
+  int argc = *argc_ref;
+  char** argv = *argv_ref;
+  /* Track argv */
+  size_t argvlen = (argc + 1)*sizeof(char*);
+  shadow_alloca(argv, argvlen);
+  initialize_static_region((uintptr_t)argv, (argc + 1)*sizeof(char*));
+
+  /* Track argument strings */
+  while (*argv) {
+    size_t arglen = strlen(*argv) + 1;
+    shadow_alloca(*argv, arglen);
+    initialize_static_region((uintptr_t)*argv, arglen);
+    argv++;
+  }
+
+  while (*environ) {
+    size_t envlen = strlen(*environ) + 1;
+    shadow_alloca(*environ, envlen);
+    initialize_static_region((uintptr_t)*environ, envlen);
+    environ++;
+  }
+}
+/* }}} */
+
+/* Program initialization {{{ */
 static void memory_init(int *argc_ref, char *** argv_ref, size_t ptr_size) {
   describe_run();
   /** Verify that the given size of a pointer matches the one in the present
@@ -144,7 +176,7 @@ static void memory_init(int *argc_ref, char *** argv_ref, size_t ptr_size) {
   DVALIDATE_SHADOW_LAYOUT;
   /* Track program arguments. */
   if (argc_ref && argv_ref)
-    argv_alloca(*argc_ref, *argv_ref);
+    argv_alloca(argc_ref, argv_ref);
   /* Tracking safe locations */
   collect_safe_locations();
   int i;
diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
index 2cce5183102..45fd1e1ab79 100644
--- a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
+++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
@@ -771,21 +771,6 @@ static void mark_readonly_region (uintptr_t addr, long size) {
 }
 /* }}} */
 
-/* Track program arguments (ARGC/ARGV) {{{ */
-static void argv_alloca(int argc,  char ** argv) {
-  /* Track a top-level container (i.e., `*argv`) */
-  shadow_alloca(argv, (argc + 1)*sizeof(char*));
-  initialize_static_region((uintptr_t)argv, (argc + 1)*sizeof(char*));
-  /* Track argument strings */
-  while (*argv) {
-    size_t arglen = strlen(*argv) + 1;
-    shadow_alloca(*argv, arglen);
-    initialize_static_region((uintptr_t)*argv, arglen);
-    argv++;
-  }
-}
-/* }}} */
-
 /* Heap allocation {{{ (malloc/calloc) */
 
 /*! \brief Amount of heap memory allocated by the program.
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_bypassed_var.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_bypassed_var.c
index 7787974a786..4e7868fd36b 100644
--- a/src/plugins/e-acsl/tests/runtime/oracle/gen_bypassed_var.c
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_bypassed_var.c
@@ -4,7 +4,6 @@ int main(int argc, char const **argv)
 {
   int __retres;
   __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8);
-  __e_acsl_store_block((void *)(& argc),(size_t)4);
   goto L;
   {
     int *p;
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_mainargs.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_mainargs.c
index f0a7e6b8479..6377f308afc 100644
--- a/src/plugins/e-acsl/tests/runtime/oracle/gen_mainargs.c
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_mainargs.c
@@ -9,8 +9,6 @@ int main(int argc, char **argv)
   /*@ assert \valid(&argc); */
   {
     int __gen_e_acsl_valid;
-    __e_acsl_store_block((void *)(& argv),(size_t)8);
-    __e_acsl_store_block((void *)(& argc),(size_t)4);
     __gen_e_acsl_valid = __e_acsl_valid((void *)(& argc),sizeof(int),
                                         (void *)(& argc),(void *)(& argc));
     __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main",
diff --git a/src/plugins/e-acsl/visit.ml b/src/plugins/e-acsl/visit.ml
index 767ea2bc422..2bfb8b9f0af 100644
--- a/src/plugins/e-acsl/visit.ml
+++ b/src/plugins/e-acsl/visit.ml
@@ -524,8 +524,10 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
       if self#is_first_stmt kf stmt then
         (* JS: should be done in the new project? *)
         let env =
-          if generate then Memory.store env kf (Kernel_function.get_formals kf)
-          else env
+          if generate && not is_main then
+            Memory.store env kf (Kernel_function.get_formals kf)
+          else
+            env
         in
         (* translate the precondition of the function *)
         if Dup_functions.is_generated (Extlib.the self#current_kf) then
-- 
GitLab