From 7560a41adc9415f91514b8c810068e38e6c0a648 Mon Sep 17 00:00:00 2001
From: Fonenantsoa Maurica <maurica.fonenantsoa@gmail.com>
Date: Tue, 13 Nov 2018 19:27:25 +0100
Subject: [PATCH] Julien's review no.1:  - Safe locations are ok but need to
 increase TLS to 32 Mo for the libxml usecase  - Fix order of operations
 during memory initialization  - TODO: memory allocated before main are not
 seen as being valid

---
 src/plugins/e-acsl/doc/Changelog              |  4 +-
 src/plugins/e-acsl/share/e-acsl/e_acsl.h      |  2 +-
 .../share/e-acsl/e_acsl_safe_locations.h      | 10 ++--
 .../segment_model/e_acsl_segment_mmodel.c     | 19 ++++---
 .../segment_model/e_acsl_segment_tracking.h   |  2 +-
 .../segment_model/e_acsl_shadow_layout.h      | 41 ++++++++-----
 .../e-acsl/tests/segment-only/constructor.c   |  7 ---
 .../oracle/constructor.res.oracle             | 10 ++--
 .../segment-only/oracle/gen_constructor.c     | 57 -------------------
 9 files changed, 51 insertions(+), 101 deletions(-)

diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog
index 36f1ff2a80e..83371e18524 100644
--- a/src/plugins/e-acsl/doc/Changelog
+++ b/src/plugins/e-acsl/doc/Changelog
@@ -23,8 +23,10 @@
 Plugin E-ACSL 18.0 (Argon)
 ##########################
 
+-* runtime      [2018/11/13] Fix bug #!2405 about memory initialization
+                in presence of GCC constructors.
 -* E-ACSL       [2018/10/23] Fix bug #2406 about monitoring of variables
-	        with incomplete types.
+                with incomplete types.
 -* E-ACSL       [2018/10/04] Fix bug #2386 about incorrect typing when
                 performing pointer subtraction.
 -* E-ACSL       [2018/10/04] Support for \at on purely logic variables.
diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl.h b/src/plugins/e-acsl/share/e-acsl/e_acsl.h
index d217505a2d6..e25be516e6c 100644
--- a/src/plugins/e-acsl/share/e-acsl/e_acsl.h
+++ b/src/plugins/e-acsl/share/e-acsl/e_acsl.h
@@ -177,7 +177,7 @@ int posix_memalign(void **memptr, size_t alignment, size_t size)
 /************************************************************************/
 
 /*! \brief Initialize memory locations. */
-void mspaces_init(int *argc_ref, char *** argv_ref)
+void mspaces_init()
   __attribute__((FC_BUILTIN));
 
 /*! \brief Initialize memory tracking state.
diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_safe_locations.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_safe_locations.h
index 78a52b13685..d98a944cc10 100644
--- a/src/plugins/e-acsl/share/e-acsl/e_acsl_safe_locations.h
+++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_safe_locations.h
@@ -69,11 +69,9 @@ extern FILE *stderr;		/* Standard error output stream. */
 
 static void collect_safe_locations() {
   /* Tracking of errno and standard streams */
-  /* TODO: how to corrrectly add the following locations
-     in presence of contructors? */
-  // add_safe_location((uintptr_t)&errno, sizeof(int), "errno");
-  // add_safe_location((uintptr_t)stdout, sizeof(FILE), "stdout");
-  // add_safe_location((uintptr_t)stderr, sizeof(FILE), "stderr");
-  // add_safe_location((uintptr_t)stdin, sizeof(FILE), "stdin");
+  add_safe_location((uintptr_t)&errno, sizeof(int), "errno");
+  add_safe_location((uintptr_t)stdout, sizeof(FILE), "stdout");
+  add_safe_location((uintptr_t)stderr, sizeof(FILE), "stderr");
+  add_safe_location((uintptr_t)stdin, sizeof(FILE), "stdin");
 }
 #endif
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 033325efd97..eae9f787e3a 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
@@ -195,17 +195,13 @@ extern int main(void);
 
 int MSPACES_INIT = 0;
 
-void mspaces_init(int *argc_ref, char *** argv_ref) {
+void mspaces_init() {
   if(MSPACES_INIT) return;
   describe_run();
   make_memory_spaces(64*MB, get_heap_size());
-  /* Lift stack limit to account for extra stack memory overhead.  */
-  increase_stack_limit(get_stack_size()*2);
-  /* Allocate and log shadow memory layout of the execution */
-  init_shadow_layout(argc_ref, argv_ref);
-  //DEBUG_PRINT_LAYOUT;
-  /* Make sure the layout holds */
-  DVALIDATE_SHADOW_LAYOUT;
+  /* Allocate and log shadow memory layout of the execution.
+    Case of the heap, globals and tls. */
+  init_shadow_layout_heap_global_tls();
   MSPACES_INIT = 1;
 }
 
@@ -217,6 +213,13 @@ void memory_init(int *argc_ref, char *** argv_ref, size_t ptr_size) {
   arch_assert(ptr_size);
   /* Initialize report file with debug logs (only in debug mode). */
   initialize_report_file(argc_ref, argv_ref);
+  /* Lift stack limit to account for extra stack memory overhead.  */
+  increase_stack_limit(get_stack_size()*2);
+  /* Allocate and log shadow memory layout of the execution. Case of stack. */
+  init_shadow_layout_stack(argc_ref, argv_ref);
+  //DEBUG_PRINT_LAYOUT;
+  /* Make sure the layout holds */
+  DVALIDATE_SHADOW_LAYOUT;
   /* Track program arguments. */
   if (argc_ref && argv_ref)
     argv_alloca(argc_ref, argv_ref);
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 9a093e62ae0..e3cf2c42b9e 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
@@ -895,7 +895,7 @@ extern int MSPACES_INIT;
  *    returned pointer shall not be used to access an object." */
 void* malloc(size_t size) {
   if(! MSPACES_INIT) {
-    mspaces_init(0, 0); // arguments of main are not (?) known at this point
+    mspaces_init();
     MSPACES_INIT = 1;
   }
   size_t alloc_size = ALLOC_SIZE(size);
diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h
index 0822602dd21..f7a779e8925 100644
--- a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h
+++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h
@@ -72,8 +72,12 @@ char *strerror(int errnum);
 /*! \brief Size of a program's heap */
 #define PGM_HEAP_SIZE (E_ACSL_HEAP_SIZE * MB)
 
-/*! \brief Size of a program's Thread-local storage (TLS) */
-#define PGM_TLS_SIZE (16 * MB)
+/*! \brief Size of a program's Thread-local storage (TLS).
+  Standard streams stdin, stdout and stderr are put here.
+  Some libraries such as libxml use it quite a lot:
+  it may occur that the given size is not enough,
+  in which case it MUST be increased. */
+#define PGM_TLS_SIZE (32 * MB)
 
 /*! \brief Mspace padding used by shadow segments. This is to make sure that
  * some allocation which exceeds the size of an initial memspace does not
@@ -350,18 +354,9 @@ static void set_shadow_segment(memory_segment *seg, memory_segment *parent,
 
 /*! \brief Initialize memory layout, i.e., determine bounds of program segments,
  * allocate shadow memory spaces and compute offsets. This function populates
- * global struct ::memory_layout holding that information with data. */
-static void init_shadow_layout(int *argc_ref, char ***argv_ref) {
-  memory_partition *pheap = &mem_layout.heap;
-  set_application_segment(&pheap->application, get_heap_start(),
-    get_heap_size(), "heap", mem_spaces.heap_mspace);
-  set_shadow_segment(&pheap->primary, &pheap->application, 1, "heap_primary");
-  set_shadow_segment(&pheap->secondary, &pheap->application, 8, "heap_secondary");
-#ifdef E_ACSL_TEMPORAL
-  set_shadow_segment(&pheap->temporal_primary, &pheap->application, 1, "temporal_heap_primary");
-  set_shadow_segment(&pheap->temporal_secondary, &pheap->application, 1, "temporal_heap_secondary");
-#endif
-
+ * global struct ::memory_layout holding that information with data.
+   Case of the stack. */
+static void init_shadow_layout_stack(int *argc_ref, char ***argv_ref) {
   memory_partition *pstack = &mem_layout.stack;
   set_application_segment(&pstack->application, get_stack_start(argc_ref, argv_ref),
     get_stack_size(), "stack", NULL);
@@ -372,6 +367,24 @@ static void init_shadow_layout(int *argc_ref, char ***argv_ref) {
   set_shadow_segment(&pstack->temporal_secondary, &pstack->application, 1, "temporal_stack_secondary");
 #endif
 
+  mem_layout.is_initialized = 1;
+}
+
+/*! \brief Initialize memory layout, i.e., determine bounds of program segments,
+ * allocate shadow memory spaces and compute offsets. This function populates
+ * global struct ::memory_layout holding that information with data.
+   Case of the heap, globals and tls. */
+static void init_shadow_layout_heap_global_tls() {
+  memory_partition *pheap = &mem_layout.heap;
+  set_application_segment(&pheap->application, get_heap_start(),
+    get_heap_size(), "heap", mem_spaces.heap_mspace);
+  set_shadow_segment(&pheap->primary, &pheap->application, 1, "heap_primary");
+  set_shadow_segment(&pheap->secondary, &pheap->application, 8, "heap_secondary");
+#ifdef E_ACSL_TEMPORAL
+  set_shadow_segment(&pheap->temporal_primary, &pheap->application, 1, "temporal_heap_primary");
+  set_shadow_segment(&pheap->temporal_secondary, &pheap->application, 1, "temporal_heap_secondary");
+#endif
+
   memory_partition *pglobal = &mem_layout.global;
   set_application_segment(&pglobal->application, get_global_start(),
     get_global_size(), "global", NULL);
diff --git a/src/plugins/e-acsl/tests/segment-only/constructor.c b/src/plugins/e-acsl/tests/segment-only/constructor.c
index 68df399f553..6600992870e 100644
--- a/src/plugins/e-acsl/tests/segment-only/constructor.c
+++ b/src/plugins/e-acsl/tests/segment-only/constructor.c
@@ -2,7 +2,6 @@
    COMMENT: bts #2405. Memory not initialized for code executed before main.
 */
 
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -15,11 +14,5 @@ void f() {
 
 int main() {
   printf("main\n");
-  int *p = &errno;
-  // TODO: see e_acsl_safe_locations.h regarding the standard streams
-  /*@ assert ! \valid(p);      */ ;
-  /*@ assert ! \valid(stderr); */ ;
-  /*@ assert ! \valid(stdin);  */ ;
-  /*@ assert ! \valid(stdout); */ ;
   return 0;
 }
\ No newline at end of file
diff --git a/src/plugins/e-acsl/tests/segment-only/oracle/constructor.res.oracle b/src/plugins/e-acsl/tests/segment-only/oracle/constructor.res.oracle
index 71defa5cfea..fb1184a3e56 100644
--- a/src/plugins/e-acsl/tests/segment-only/oracle/constructor.res.oracle
+++ b/src/plugins/e-acsl/tests/segment-only/oracle/constructor.res.oracle
@@ -5,18 +5,16 @@
 [e-acsl] Warning: annotating undefined function `printf_va_2':
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
-[e-acsl] tests/segment-only/constructor.c:17: Warning: 
+[e-acsl] tests/segment-only/constructor.c:16: Warning: 
   E-ACSL construct `logic function application' is not yet supported.
   Ignoring annotation.
-[e-acsl] tests/segment-only/constructor.c:17: Warning: 
+[e-acsl] tests/segment-only/constructor.c:16: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
-[e-acsl] tests/segment-only/constructor.c:11: Warning: 
+[e-acsl] tests/segment-only/constructor.c:10: Warning: 
   E-ACSL construct `logic function application' is not yet supported.
   Ignoring annotation.
-[e-acsl] tests/segment-only/constructor.c:11: Warning: 
+[e-acsl] tests/segment-only/constructor.c:10: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] translation done in project "e-acsl".
-[eva:alarm] tests/segment-only/constructor.c:19: Warning: 
-  assertion got status invalid (stopping propagation).
diff --git a/src/plugins/e-acsl/tests/segment-only/oracle/gen_constructor.c b/src/plugins/e-acsl/tests/segment-only/oracle/gen_constructor.c
index 995599d7c5c..eefdbbe0fd9 100644
--- a/src/plugins/e-acsl/tests/segment-only/oracle/gen_constructor.c
+++ b/src/plugins/e-acsl/tests/segment-only/oracle/gen_constructor.c
@@ -1,5 +1,4 @@
 /* Generated by Frama-C */
-#include "errno.h"
 #include "stdio.h"
 #include "stdlib.h"
 char *__gen_e_acsl_literal_string_2;
@@ -24,14 +23,6 @@ void __e_acsl_globals_init(void)
   __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("f\n"));
   __e_acsl_full_init((void *)__gen_e_acsl_literal_string);
   __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string);
-  __e_acsl_store_block((void *)(& stdout),(size_t)8);
-  __e_acsl_full_init((void *)(& stdout));
-  __e_acsl_store_block((void *)(& stdin),(size_t)8);
-  __e_acsl_full_init((void *)(& stdin));
-  __e_acsl_store_block((void *)(& stderr),(size_t)8);
-  __e_acsl_full_init((void *)(& stderr));
-  __e_acsl_store_block((void *)(& errno),(size_t)4);
-  __e_acsl_full_init((void *)(& errno));
   return;
 }
 
@@ -41,55 +32,7 @@ int main(void)
   __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
   __e_acsl_globals_init();
   __gen_e_acsl_printf_va_2(__gen_e_acsl_literal_string_2);
-  int *p = & errno;
-  __e_acsl_store_block((void *)(& p),(size_t)8);
-  __e_acsl_full_init((void *)(& p));
-  /*@ assert ¬\valid(p); */
-  {
-    int __gen_e_acsl_initialized;
-    int __gen_e_acsl_and;
-    __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p),
-                                                    sizeof(int *));
-    if (__gen_e_acsl_initialized) {
-      int __gen_e_acsl_valid;
-      __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p,
-                                          (void *)(& p));
-      __gen_e_acsl_and = __gen_e_acsl_valid;
-    }
-    else __gen_e_acsl_and = 0;
-    __e_acsl_assert(! __gen_e_acsl_and,(char *)"Assertion",(char *)"main",
-                    (char *)"!\\valid(p)",19);
-  }
-  /*@ assert ¬\valid(__fc_stderr); */
-  {
-    int __gen_e_acsl_valid_2;
-    __gen_e_acsl_valid_2 = __e_acsl_valid((void *)stderr,sizeof(FILE),
-                                          (void *)stderr,(void *)(& stderr));
-    __e_acsl_assert(! __gen_e_acsl_valid_2,(char *)"Assertion",
-                    (char *)"main",(char *)"!\\valid(__fc_stderr)",20);
-  }
-  /*@ assert ¬\valid(__fc_stdin); */
-  {
-    int __gen_e_acsl_valid_3;
-    __gen_e_acsl_valid_3 = __e_acsl_valid((void *)stdin,sizeof(FILE),
-                                          (void *)stdin,(void *)(& stdin));
-    __e_acsl_assert(! __gen_e_acsl_valid_3,(char *)"Assertion",
-                    (char *)"main",(char *)"!\\valid(__fc_stdin)",21);
-  }
-  /*@ assert ¬\valid(__fc_stdout); */
-  {
-    int __gen_e_acsl_valid_4;
-    __gen_e_acsl_valid_4 = __e_acsl_valid((void *)stdout,sizeof(FILE),
-                                          (void *)stdout,(void *)(& stdout));
-    __e_acsl_assert(! __gen_e_acsl_valid_4,(char *)"Assertion",
-                    (char *)"main",(char *)"!\\valid(__fc_stdout)",22);
-  }
   __retres = 0;
-  __e_acsl_delete_block((void *)(& stdout));
-  __e_acsl_delete_block((void *)(& stdin));
-  __e_acsl_delete_block((void *)(& stderr));
-  __e_acsl_delete_block((void *)(& errno));
-  __e_acsl_delete_block((void *)(& p));
   __e_acsl_memory_clean();
   return __retres;
 }
-- 
GitLab