[PATCH 4/7] sampling-asan: Support old version of C (before C11 standard)

Sung-hun Kim sfoon.kim@samsung.com
Fri Sep 19 01:30:45 GMT 2025


Prior to the C11 standard, the C language did not include support for the
_Generic macro, which is commonly used for mimicking polymorphism. To
address this limitation, I have implemented an alternative approach using
a void pointer and a variable option type to differentiate function calls.

This change ensures compatiblity with the older C standards, allowing
sampling-asan to codes implemented on the old C standards.

Signed-off-by: Sung-hun Kim <sfoon.kim@samsung.com>
---
 sampling-asan/samasan_init.c            | 171 ++++++++++++++++--------
 sampling-asan/samasan_variable_init.def |  33 +++--
 2 files changed, 127 insertions(+), 77 deletions(-)

diff --git a/sampling-asan/samasan_init.c b/sampling-asan/samasan_init.c
index 3a53068357..0136fe9a0d 100644
--- a/sampling-asan/samasan_init.c
+++ b/sampling-asan/samasan_init.c
@@ -105,9 +105,14 @@ samasan_set_variable_range (samasan_option_t option, uint32_t max,
   samasan_configurables[option].range.min = min;
 }
 
-/* TODO: _Generic is supported since C11 standard (ISO/IEC 9899:2011)
-   Thus, the version of C should be checked and an alternative should be
-   provided for the unsupported versions. */
+/* _Generic is supported since C11 standard (ISO/IEC 9899:2011). */
+#if __STDC_VERSION__ >= 201112L
+#define __C_GENERIC_SUPPORTED__ true
+#else
+#define __C_GENERIC_SUPPORTED__ false
+#endif
+
+#if __C_GENERIC_SUPPORTED__
 /* A boolean type variable is treated as a integer type variable in C,
    so I assign samasan_set_variable_bool to the integer type. */
 #define samasan_set_variable(index, value) \
@@ -115,13 +120,42 @@ samasan_set_variable_range (samasan_option_t option, uint32_t max,
      uint32_t: samasan_set_variable_uint, \
      const char *: samasan_set_variable_char, \
      char *: samasan_set_variable_char, \
-     int: samasan_set_variable_bool) (index, value)
+     bool: samasan_set_variable_bool) (index, value)
+#else /* __C_GENERIC_SUPPORTED__ */
+#define OPTION_IS_UINT(option) (option == SAMASAN_MAX_ALLOC_SIZE || \
+  option == SAMASAN_MAX_ON_GOING_ALLOCATIONS || \
+  option == SAMASAN_PARTITION_SIZE || \
+  option == SAMASAN_SAMPLING_RATE || \
+  option == SAMASAN_CHUNK_PICK)
+#define OPTION_IS_CHAR(option) (option == SAMASAN_OUTPUT_PATH)
+#define OPTION_IS_BOOL(option) (option == SAMASAN_ENABLE || \
+  option == SAMASAN_PAUSE_ON_FORK)
+
+static void __samasan_set_variable
+(samasan_option_t option, void *value)
+{
+  if (OPTION_IS_UINT (option)) {
+    uint32_t *val = (uint32_t *) value;
+    samasan_set_variable_uint (option, *val);
+  } else if (OPTION_IS_CHAR (option)) {
+    char **val = (char **) value;
+    samasan_set_variable_char (option, *val);
+  } else if (OPTION_IS_BOOL (option)) {
+    bool *val = (bool *) value;
+    samasan_set_variable_bool (option, *val);
+  } else
+    samasan_exit_with_message ("Unknown variable type. Abort.\n");
+}
+
+#define samasan_set_variable(option, value) \
+  __samasan_set_variable (option, (void *) &value)
+#endif /* __C_GENERIC_SUPPORTED__ */
 
 #define samasan_get_variable(index) samasan_configurables[index].value
 
 #define samasan_check_variable_range(index, value) \
   (value >= samasan_configurables[index].range.min && \
-  value <= samasan_configurables[index].range.max)
+   value <= samasan_configurables[index].range.max)
 
 #define samasan_get_enabled() samasan_get_variable (SAMASAN_ENABLE).b_value
 #define samasan_get_output_path() \
@@ -139,44 +173,6 @@ samasan_set_variable_range (samasan_option_t option, uint32_t max,
 #define samasan_get_chunk_pick_style() \
           samasan_get_variable (SAMASAN_CHUNK_PICK).i_value
 
-#include "samasan_variable_init.def"
-
-static void
-samasan_variable_init (void)
-{
-  if (SAMASAN_UNLIKELY (!samasan_configurables))
-    return;
-
-  samasan_set_variable (SAMASAN_ENABLE,
-            DEFAULT_SAMASAN_ENABLED);
-  samasan_set_variable (SAMASAN_SAMPLING_RATE,
-            DEFAULT_SAMASAN_SAMPLING_RATE);
-  samasan_set_variable_range (SAMASAN_SAMPLING_RATE,
-            MAX_SAMASAN_SAMPLING_RATE,
-            MIN_SAMASAN_SAMPLING_RATE);
-  samasan_set_variable (SAMASAN_MAX_ALLOC_SIZE,
-			      DEFAULT_SAMASAN_MAX_ALLOC_SIZE);
-  samasan_set_variable_range (SAMASAN_MAX_ALLOC_SIZE,
-			      MAX_SAMASAN_MAX_ALLOC_SIZE,
-            MIN_SAMASAN_MAX_ALLOC_SIZE);
-  samasan_set_variable (SAMASAN_MAX_ON_GOING_ALLOCATIONS,
-			      DEFAULT_SAMASAN_MAX_ON_GOING_ALLOCATIONS);
-  samasan_set_variable_range (SAMASAN_MAX_ON_GOING_ALLOCATIONS,
-			      MAX_SAMASAN_MAX_ON_GOING_ALLOCATIONS,
-            MIN_SAMASAN_MAX_ON_GOING_ALLOCATIONS);
-  samasan_set_variable (SAMASAN_OUTPUT_PATH,
-            DEFAULT_SAMASAN_OUTPUT_PATH);
-  samasan_set_variable (SAMASAN_PARTITION_SIZE,
-            DEFAULT_SAMASAN_PARTITION_SIZE);
-  samasan_set_variable_range (SAMASAN_PARTITION_SIZE,
-            MAX_SAMASAN_PARTITION_SIZE,
-            MIN_SAMASAN_PARTITION_SIZE);
-  samasan_set_variable (SAMASAN_PAUSE_ON_FORK,
-            DEFAULT_SAMASAN_PAUSE_ON_FORK);
-  samasan_set_variable (SAMASAN_CHUNK_PICK,
-            DEFAULT_SAMASAN_CHUNK_PICK);
-}
-
 static bool
 import_samasan_variable (int type, const char *val)
 {
@@ -184,10 +180,12 @@ import_samasan_variable (int type, const char *val)
     {
     case SAMASAN_ENABLE:
       {
-	if (!strcmp (val, "on") || !strcmp (val, "enable")
-	    || !strcmp (val, "yes") || !strcmp (val, "true"))
-	  samasan_set_variable (SAMASAN_ENABLE, true);
-	break;
+  bool var = false;
+  if (!strcmp (val, "on") || !strcmp (val, "enable")
+      || !strcmp (val, "yes") || !strcmp (val, "true"))
+    var = true;
+  samasan_set_variable (SAMASAN_ENABLE, var);
+  break;
       }
     case SAMASAN_MAX_ALLOC_SIZE:
   {
@@ -207,7 +205,7 @@ import_samasan_variable (int type, const char *val)
     if (!converted)
       return false;
     if (!samasan_check_variable_range (SAMASAN_MAX_ON_GOING_ALLOCATIONS,
-				       converted))
+				                               converted))
       return false;
     samasan_set_variable (SAMASAN_MAX_ON_GOING_ALLOCATIONS, converted);
     break;
@@ -229,34 +227,34 @@ import_samasan_variable (int type, const char *val)
   }
     case SAMASAN_PARTITION_SIZE:
   {
-    int32_t converted = (int32_t) atoi (val);
-    if (converted < 0)
-      return false;
+    uint32_t converted = (uint32_t) atoi (val);
     if (!samasan_check_variable_range (SAMASAN_PARTITION_SIZE,
-                                       (uint32_t) converted))
+                                       converted))
       return false;
-    samasan_set_variable (SAMASAN_PARTITION_SIZE, (uint32_t) converted);
+    samasan_set_variable (SAMASAN_PARTITION_SIZE, converted);
     break;
   }
     case SAMASAN_PAUSE_ON_FORK:
   {
+    bool var = false;
 	  if (!strcmp (val, "on") || !strcmp (val, "enable")
 	      || !strcmp (val, "yes") || !strcmp (val, "true"))
-	    samasan_set_variable (SAMASAN_PAUSE_ON_FORK, true);
-    else
-      samasan_set_variable (SAMASAN_PAUSE_ON_FORK, false);
+      var = true;
+	  samasan_set_variable (SAMASAN_PAUSE_ON_FORK, var);
 	  break;
   }
     case SAMASAN_CHUNK_PICK:
   {
+    uint32_t pick;
 	  if (!strcmp (val, "left") || !strcmp (val, "LEFT"))
-	    samasan_set_variable (SAMASAN_CHUNK_PICK, (uint32_t) PICK_FROM_LEFT);
+      pick = (uint32_t) PICK_FROM_LEFT;
     else if (!strcmp (val, "right") || !strcmp (val, "RIGHT"))
-      samasan_set_variable (SAMASAN_CHUNK_PICK, (uint32_t) PICK_FROM_RIGHT);
+      pick = (uint32_t) PICK_FROM_RIGHT;
     else if (!strcmp (val, "center") || !strcmp (val, "CENTER"))
-      samasan_set_variable (SAMASAN_CHUNK_PICK, (uint32_t) PICK_CENTER);
+      pick = (uint32_t) PICK_CENTER;
     else
       return false;
+	  samasan_set_variable (SAMASAN_CHUNK_PICK, pick);
 	  break;
   }
     default:
@@ -265,6 +263,61 @@ import_samasan_variable (int type, const char *val)
   return true;
 }
 
+static inline bool import_samasan_variable_range
+(samasan_option_t option, const char *max, const char *min)
+{
+  uint32_t minval, maxval;
+
+  minval = (uint32_t) atoi (min);
+  maxval = (uint32_t) atoi (max);
+  if (maxval < minval)
+    return false;
+
+  samasan_set_variable_range (option, maxval, minval);
+  return true;
+}
+
+#include "samasan_variable_init.def"
+
+static void
+samasan_variable_init (void)
+{
+  if (SAMASAN_UNLIKELY (!samasan_configurables))
+    return;
+
+  /* variable range initialization */
+  import_samasan_variable_range (SAMASAN_SAMPLING_RATE,
+            MAX_SAMASAN_SAMPLING_RATE,
+            MIN_SAMASAN_SAMPLING_RATE);
+  import_samasan_variable_range (SAMASAN_MAX_ALLOC_SIZE,
+			      MAX_SAMASAN_MAX_ALLOC_SIZE,
+            MIN_SAMASAN_MAX_ALLOC_SIZE);
+  import_samasan_variable_range (SAMASAN_MAX_ON_GOING_ALLOCATIONS,
+			      MAX_SAMASAN_MAX_ON_GOING_ALLOCATIONS,
+            MIN_SAMASAN_MAX_ON_GOING_ALLOCATIONS);
+  import_samasan_variable_range (SAMASAN_PARTITION_SIZE,
+            MAX_SAMASAN_PARTITION_SIZE,
+            MIN_SAMASAN_PARTITION_SIZE);
+
+  /* configurable variables initialization */
+  import_samasan_variable (SAMASAN_ENABLE,
+            DEFAULT_SAMASAN_ENABLED);
+  import_samasan_variable (SAMASAN_SAMPLING_RATE,
+            DEFAULT_SAMASAN_SAMPLING_RATE);
+  import_samasan_variable (SAMASAN_MAX_ALLOC_SIZE,
+			      DEFAULT_SAMASAN_MAX_ALLOC_SIZE);
+  import_samasan_variable (SAMASAN_MAX_ON_GOING_ALLOCATIONS,
+			      DEFAULT_SAMASAN_MAX_ON_GOING_ALLOCATIONS);
+  import_samasan_variable (SAMASAN_OUTPUT_PATH,
+            DEFAULT_SAMASAN_OUTPUT_PATH);
+  import_samasan_variable (SAMASAN_PARTITION_SIZE,
+            DEFAULT_SAMASAN_PARTITION_SIZE);
+  import_samasan_variable (SAMASAN_PAUSE_ON_FORK,
+            DEFAULT_SAMASAN_PAUSE_ON_FORK);
+  import_samasan_variable (SAMASAN_CHUNK_PICK,
+            DEFAULT_SAMASAN_CHUNK_PICK);
+}
+
 void
 samasan_disable (void)
 {
diff --git a/sampling-asan/samasan_variable_init.def b/sampling-asan/samasan_variable_init.def
index 954ce20eeb..3a5441bc15 100644
--- a/sampling-asan/samasan_variable_init.def
+++ b/sampling-asan/samasan_variable_init.def
@@ -16,25 +16,22 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* All integer values defined in this file should have type of
-   unsigned integer. */
-
-#define DEFAULT_SAMASAN_ENABLED false
-#define DEFAULT_SAMASAN_SAMPLING_RATE 500u /* 0.005 */
-#define DEFAULT_SAMASAN_MAX_ALLOC_SIZE 4096u
-#define DEFAULT_SAMASAN_MAX_ON_GOING_ALLOCATIONS 100u
+#define DEFAULT_SAMASAN_ENABLED "false"
+#define DEFAULT_SAMASAN_SAMPLING_RATE "0.005" /* 0.005 */
+#define DEFAULT_SAMASAN_MAX_ALLOC_SIZE "4096"
+#define DEFAULT_SAMASAN_MAX_ON_GOING_ALLOCATIONS "100"
 #define DEFAULT_SAMASAN_OUTPUT_PATH "stderr"
-#define DEFAULT_SAMASAN_PARTITION_SIZE 4096u /* 1 page */
-#define DEFAULT_SAMASAN_PAUSE_ON_FORK true
-#define DEFAULT_SAMASAN_CHUNK_PICK PICK_CENTER /* defined in samasan_allocate.h */
+#define DEFAULT_SAMASAN_PARTITION_SIZE "4096" /* 1 page */
+#define DEFAULT_SAMASAN_PAUSE_ON_FORK "true"
+#define DEFAULT_SAMASAN_CHUNK_PICK "CENTER"
 
 /* MAX and MIN define a range of the given configuration. */
-#define MAX_SAMASAN_SAMPLING_RATE 100000u
-#define MAX_SAMASAN_MAX_ALLOC_SIZE 40960u
-#define MAX_SAMASAN_MAX_ON_GOING_ALLOCATIONS 10000u
-#define MAX_SAMASAN_PARTITION_SIZE 40960u /* 10 pages */
+#define MAX_SAMASAN_SAMPLING_RATE "100000"
+#define MAX_SAMASAN_MAX_ALLOC_SIZE "40960"
+#define MAX_SAMASAN_MAX_ON_GOING_ALLOCATIONS "10000"
+#define MAX_SAMASAN_PARTITION_SIZE "40960" /* 10 pages */
 
-#define MIN_SAMASAN_SAMPLING_RATE 0u
-#define MIN_SAMASAN_MAX_ALLOC_SIZE 4096u
-#define MIN_SAMASAN_MAX_ON_GOING_ALLOCATIONS 1u
-#define MIN_SAMASAN_PARTITION_SIZE 0u /* no partition page */
+#define MIN_SAMASAN_SAMPLING_RATE "0"
+#define MIN_SAMASAN_MAX_ALLOC_SIZE "4096"
+#define MIN_SAMASAN_MAX_ON_GOING_ALLOCATIONS "1"
+#define MIN_SAMASAN_PARTITION_SIZE "0" /* no partition page */
-- 
2.25.1



More information about the Libc-alpha mailing list