Selaa lähdekoodia

Make const ptr assign as function call in clang

- This can act as memory barrier in clang to avoid
  read before assign of a const ptr

Signed-off-by: LoveSy <shana@zju.edu.cn>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
YU Jincheng 2 vuotta sitten
vanhempi
commit
5156b24553
7 muutettua tiedostoa jossa 38 lisäystä ja 12 poistoa
  1. 1 1
      coreutils/test.c
  2. 15 6
      include/libbb.h
  3. 1 0
      libbb/Kbuild.src
  4. 1 1
      libbb/appletlib.c
  5. 16 0
      libbb/const_hack.c
  6. 1 1
      libbb/lineedit.c
  7. 3 3
      shell/ash.c

+ 1 - 1
coreutils/test.c

@@ -446,7 +446,7 @@ extern struct test_statics *BB_GLOBAL_CONST test_ptr_to_statics;
 #define leaving         (S.leaving      )
 
 #define INIT_S() do { \
-	ASSIGN_CONST_PTR(test_ptr_to_statics, xzalloc(sizeof(S))); \
+	XZALLOC_CONST_PTR(&test_ptr_to_statics, sizeof(S)); \
 } while (0)
 #define DEINIT_S() do { \
 	free(group_array); \

+ 15 - 6
include/libbb.h

@@ -2280,6 +2280,7 @@ extern const char bb_PATH_root_path[] ALIGN1; /* BB_PATH_ROOT_PATH */
 extern const int const_int_0;
 //extern const int const_int_1;
 
+
 /* This struct is deliberately not defined. */
 /* See docs/keep_data_small.txt */
 struct globals;
@@ -2304,23 +2305,31 @@ static ALWAYS_INLINE void* not_const_pp(const void *p)
 	);
 	return pp;
 }
+# define ASSIGN_CONST_PTR(pptr, v) do { \
+	*(void**)not_const_pp(pptr) = (void*)(v); \
+	barrier(); \
+} while (0)
+/* XZALLOC_CONST_PTR() is an out-of-line function to prevent
+ * clang from reading pointer before it is assigned.
+ */
+void XZALLOC_CONST_PTR(const void *pptr, size_t size) FAST_FUNC;
 #else
-static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; }
-#endif
-
-#define ASSIGN_CONST_PTR(p, v) do { \
-	*(void**)not_const_pp(&p) = (void*)(v); \
+# define ASSIGN_CONST_PTR(pptr, v) do { \
+	*(void**)(pptr) = (void*)(v); \
 	/* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
 	barrier(); \
 } while (0)
+# define XZALLOC_CONST_PTR(pptr, size) ASSIGN_CONST_PTR(pptr, xzalloc(size))
+#endif
 
-#define SET_PTR_TO_GLOBALS(x) ASSIGN_CONST_PTR(ptr_to_globals, x)
+#define SET_PTR_TO_GLOBALS(x) ASSIGN_CONST_PTR(&ptr_to_globals, x)
 #define FREE_PTR_TO_GLOBALS() do { \
 	if (ENABLE_FEATURE_CLEAN_UP) { \
 		free(ptr_to_globals); \
 	} \
 } while (0)
 
+
 /* You can change LIBBB_DEFAULT_LOGIN_SHELL, but don't use it,
  * use bb_default_login_shell and following defines.
  * If you change LIBBB_DEFAULT_LOGIN_SHELL,

+ 1 - 0
libbb/Kbuild.src

@@ -24,6 +24,7 @@ lib-y += chomp.o
 lib-y += compare_string_array.o
 lib-y += concat_path_file.o
 lib-y += concat_subpath_file.o
+lib-y += const_hack.o
 lib-y += copy_file.o
 lib-y += copyfd.o
 lib-y += crc32.o

+ 1 - 1
libbb/appletlib.c

@@ -247,7 +247,7 @@ void lbb_prepare(const char *applet
 		IF_FEATURE_INDIVIDUAL(, char **argv))
 {
 #ifdef bb_cached_errno_ptr
-	ASSIGN_CONST_PTR(bb_errno, get_perrno());
+	ASSIGN_CONST_PTR(&bb_errno, get_perrno());
 #endif
 	applet_name = applet;
 

+ 16 - 0
libbb/const_hack.c

@@ -0,0 +1,16 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Trick to assign a const ptr with barrier for clang
+ *
+ * Copyright (C) 2021 by YU Jincheng <shana@zju.edu.cn>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+#include "libbb.h"
+
+#if defined(__clang_major__) && __clang_major__ >= 9
+void FAST_FUNC XZALLOC_CONST_PTR(const void *pptr, size_t size)
+{
+	ASSIGN_CONST_PTR(pptr, xzalloc(size));
+}
+#endif

+ 1 - 1
libbb/lineedit.c

@@ -214,7 +214,7 @@ extern struct lineedit_statics *BB_GLOBAL_CONST lineedit_ptr_to_statics;
 #define delbuf           (S.delbuf          )
 
 #define INIT_S() do { \
-	ASSIGN_CONST_PTR(lineedit_ptr_to_statics, xzalloc(sizeof(S))); \
+	XZALLOC_CONST_PTR(&lineedit_ptr_to_statics, sizeof(S)); \
 } while (0)
 
 static void deinit_S(void)

+ 3 - 3
shell/ash.c

@@ -504,7 +504,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
 #define random_gen  (G_misc.random_gen )
 #define backgndpid  (G_misc.backgndpid )
 #define INIT_G_misc() do { \
-	ASSIGN_CONST_PTR(ash_ptr_to_globals_misc, xzalloc(sizeof(G_misc))); \
+	XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \
 	savestatus = -1; \
 	curdir = nullstr; \
 	physdir = nullstr; \
@@ -1582,7 +1582,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
 #define g_stacknleft (G_memstack.g_stacknleft)
 #define stackbase    (G_memstack.stackbase   )
 #define INIT_G_memstack() do { \
-	ASSIGN_CONST_PTR(ash_ptr_to_globals_memstack, xzalloc(sizeof(G_memstack))); \
+	XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \
 	g_stackp = &stackbase; \
 	g_stacknxt = stackbase.space; \
 	g_stacknleft = MINSIZE; \
@@ -2213,7 +2213,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
 #endif
 #define INIT_G_var() do { \
 	unsigned i; \
-	ASSIGN_CONST_PTR(ash_ptr_to_globals_var, xzalloc(sizeof(G_var))); \
+	XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \
 	for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
 		varinit[i].flags    = varinit_data[i].flags; \
 		varinit[i].var_text = varinit_data[i].var_text; \