[LTP] [RFC] [PATCH v2] lib32: Add support for linking 32bit programs on 64bit

Cyril Hrubis chrubis@suse.cz
Thu Apr 6 14:46:41 CEST 2017


This is proof of concept for building 32bit testcases on 64bit platform.

What we do is:

* Configure test if compiler supports -m32

* Configure test if compiler supports atomic operations with -m32
  (we have to use fallbacks in tst_atomic.h otherwise)

* The directory lib32 contains symlinks of minimal set of sources
  needed to link newlib testcase + Makefile.

* The testcases.mk builds 32bit library as well if
  32bit compiler was installed (-m32 configure test was succesful)

* And finally the env_post.mk switches between adding -L path to lib or
  lib32 depeding on if -m32 was passed in global CFLAGS and/or in the
  target specific CFLAGS

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---

I've tried for quite minimalistic approach here, instead of trying to detect if
we are on 64bit machine or not we just detect if compiler supports -m32 or not
and build lib32 if we can. We will build the test library twice in case that
32bit compiler supports -m32 but that shouldn't do any harm.


---
 configure.ac                               |  1 +
 include/mk/config.mk.in                    |  2 ++
 include/mk/env_post.mk                     | 21 ++++++++++--
 include/mk/testcases.mk                    |  9 +++++
 include/tst_atomic.h                       |  3 +-
 lib32/Makefile                             | 53 ++++++++++++++++++++++++++++++
 lib32/errnos.h                             |  1 +
 lib32/safe_file_ops.c                      |  1 +
 lib32/safe_macros.c                        |  1 +
 lib32/safe_net.c                           |  1 +
 lib32/signame.h                            |  1 +
 lib32/tst_ansi_color.c                     |  1 +
 lib32/tst_checkpoint.c                     |  1 +
 lib32/tst_device.c                         |  1 +
 lib32/tst_fill_file.c                      |  1 +
 lib32/tst_kvercmp.c                        |  1 +
 lib32/tst_mkfs.c                           |  1 +
 lib32/tst_res.c                            |  1 +
 lib32/tst_resource.c                       |  1 +
 lib32/tst_run_cmd.c                        |  1 +
 lib32/tst_safe_macros.c                    |  1 +
 lib32/tst_test.c                           |  1 +
 lib32/tst_tmpdir.c                         |  1 +
 m4/ltp-m32.m4                              | 50 ++++++++++++++++++++++++++++
 testcases/kernel/syscalls/add_key/Makefile |  2 ++
 25 files changed, 155 insertions(+), 3 deletions(-)
 create mode 100644 lib32/Makefile
 create mode 120000 lib32/errnos.h
 create mode 120000 lib32/safe_file_ops.c
 create mode 120000 lib32/safe_macros.c
 create mode 120000 lib32/safe_net.c
 create mode 120000 lib32/signame.h
 create mode 120000 lib32/tst_ansi_color.c
 create mode 120000 lib32/tst_checkpoint.c
 create mode 120000 lib32/tst_device.c
 create mode 120000 lib32/tst_fill_file.c
 create mode 120000 lib32/tst_kvercmp.c
 create mode 120000 lib32/tst_mkfs.c
 create mode 120000 lib32/tst_res.c
 create mode 120000 lib32/tst_resource.c
 create mode 120000 lib32/tst_run_cmd.c
 create mode 120000 lib32/tst_safe_macros.c
 create mode 120000 lib32/tst_test.c
 create mode 120000 lib32/tst_tmpdir.c
 create mode 100644 m4/ltp-m32.m4

diff --git a/configure.ac b/configure.ac
index ecc9a26..1013812 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,5 +189,6 @@ LTP_CHECK_EPOLL_PWAIT
 LTP_CHECK_KEYUTILS_SUPPORT
 LTP_CHECK_SYNC_ADD_AND_FETCH
 LTP_CHECK_BUILTIN_CLEAR_CACHE
+LTP_CHECK_CFLAGS_M32
 
 AC_OUTPUT
diff --git a/include/mk/config.mk.in b/include/mk/config.mk.in
index dde2a9e..c7d5a96 100644
--- a/include/mk/config.mk.in
+++ b/include/mk/config.mk.in
@@ -76,6 +76,8 @@ LDFLAGS			+= $(WLDFLAGS)
 CFLAGS			+= $(DEBUG_CFLAGS) $(OPT_CFLAGS) $(WCFLAGS)
 CXXFLAGS		+= $(DEBUG_CXXFLAGS) $(OPT_CXXFLAGS) $(WCXXFLAGS)
 
+CFLAGS_M32		:= @CFLAGS_M32@
+
 LINUX_VERSION		:= @LINUX_VERSION@
 LINUX_DIR		:= @LINUX_DIR@
 LINUX_VERSION_MAJOR	:= @LINUX_VERSION_MAJOR@
diff --git a/include/mk/env_post.mk b/include/mk/env_post.mk
index 4c57fff..7d92d8a 100644
--- a/include/mk/env_post.mk
+++ b/include/mk/env_post.mk
@@ -35,8 +35,6 @@ vpath %.c $(abs_srcdir)
 # For config.h, et all.
 CPPFLAGS			+= -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/include/old/
 
-LDFLAGS				+= -L$(top_builddir)/lib
-
 ifeq ($(UCLINUX),1)
 CPPFLAGS			+= -D__UCLIBC__ -DUCLINUX
 endif
@@ -56,6 +54,25 @@ MAKE_TARGETS			:= $(filter-out $(FILTER_OUT_MAKE_TARGETS),$(MAKE_TARGETS))
 
 CLEAN_TARGETS			+= $(MAKE_TARGETS) *.o *.pyc
 
+#
+# We link against lib32 only if:
+# * -m32 wasn't passed in global (configure) CFLAGS
+# * -m32 was passed in target specific CFLAGS
+#
+# The testcases must do:
+#
+# foo: CFLAGS += $(CFLAGS_M32)
+#
+# In order to compile the test in 32bit mode on 64bit arch, which takes care of
+# the situation when -m32 is not supported by compiler, since $(CFLAGS_M32) is
+# empty and we default to linking against (possibly 64bit) lib/ directory.
+#
+ifeq ($(filter -m32,$(CFLAGS)),)
+$(MAKE_TARGETS): LDFLAGS += -L$(top_builddir)/lib$(subst -m,,$(filter -m32,$(CFLAGS)))
+else
+LDFLAGS			 += -L$(top_builddir)/lib
+endif
+
 # Majority of the files end up in testcases/bin...
 INSTALL_DIR			?= testcases/bin
 
diff --git a/include/mk/testcases.mk b/include/mk/testcases.mk
index f453f4e..687c2ec 100644
--- a/include/mk/testcases.mk
+++ b/include/mk/testcases.mk
@@ -30,8 +30,10 @@ TKI_DIR		:= testcases/kernel/include
 LSN_H		:= $(abs_top_builddir)/$(TKI_DIR)/linux_syscall_numbers.h
 
 LIBLTP_DIR	:= $(abs_top_builddir)/lib
+LIBLTP_DIR32	:= $(abs_top_builddir)/lib32
 
 LIBLTP		:= $(LIBLTP_DIR)/libltp.a
+LIBLTP32	:= $(LIBLTP_DIR32)/libltp.a
 
 $(APICMDS_DIR)/tst_kvercmp: $(APICMDS_DIR)
 	$(MAKE) -C "$^" -f "$(abs_top_srcdir)/tools/apicmds/Makefile" all
@@ -39,11 +41,18 @@ $(APICMDS_DIR)/tst_kvercmp: $(APICMDS_DIR)
 $(LIBLTP): $(LIBLTP_DIR)
 	$(MAKE) -C "$^" -f "$(abs_top_srcdir)/lib/Makefile" all
 
+$(LIBLTP32): $(LIBLTP_DIR32)
+	$(MAKE) -C "$^" -f "$(abs_top_srcdir)/lib32/Makefile" all
+
 $(LSN_H): $(abs_top_builddir)/$(TKI_DIR)
 	$(MAKE) -C "$^" -f "$(abs_top_srcdir)/$(TKI_DIR)/Makefile" all
 
 MAKE_DEPS	:= $(LIBLTP) $(LSN_H)
 
+ifneq ($(CFLAGS_M32),)
+MAKE_DEPS	+= $(LIBLTP32)
+endif
+
 # For linux_syscall_numbers.h
 CPPFLAGS	+= -I$(abs_top_builddir)/$(TKI_DIR)
 
diff --git a/include/tst_atomic.h b/include/tst_atomic.h
index 35a3b34..5ee8889 100644
--- a/include/tst_atomic.h
+++ b/include/tst_atomic.h
@@ -20,7 +20,8 @@
 
 #include "config.h"
 
-#if HAVE_SYNC_ADD_AND_FETCH == 1
+#if (!defined(M32) && HAVE_SYNC_ADD_AND_FETCH == 1) \
+    || (defined(M32) && HAVE_SYNC_ADD_AND_FETCH_M32 == 1)
 static inline int tst_atomic_add_return(int i, int *v)
 {
 	return __sync_add_and_fetch(v, i);
diff --git a/lib32/Makefile b/lib32/Makefile
new file mode 100644
index 0000000..72d65e7
--- /dev/null
+++ b/lib32/Makefile
@@ -0,0 +1,53 @@
+#
+# lib32 Makefile.
+#
+# Copyright (C) 2017, Cyril Hrubis <chrubis@suse.cz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+#
+# We build the 32bit library only if -m32 is supported by the compiler
+# it looks like some 32bit compilers does not support the flag while others
+# do, hence the easiest solution is to build the library if we can.
+#
+top_srcdir		?= ..
+
+include $(top_srcdir)/include/mk/env_pre.mk
+
+ifneq ($(CFLAGS_M32),)
+
+CFLAGS			+= -DLTPLIB -m32 -DM32
+
+ifneq ($(ANDROID),1)
+FILTER_OUT_DIRS		+= android_libpthread android_librt
+else
+FILTER_OUT_LIBSRCS	+= tlibio.c tst_path_has_mnt_flags.c
+endif
+
+LIB			:= libltp.a
+
+include $(top_srcdir)/include/mk/lib.mk
+include $(top_srcdir)/include/mk/generic_trunk_target.mk
+
+else
+
+all:
+
+clean:
+
+install:
+
+endif
diff --git a/lib32/errnos.h b/lib32/errnos.h
new file mode 120000
index 0000000..caff095
--- /dev/null
+++ b/lib32/errnos.h
@@ -0,0 +1 @@
+../lib/errnos.h
\ No newline at end of file
diff --git a/lib32/safe_file_ops.c b/lib32/safe_file_ops.c
new file mode 120000
index 0000000..eeb29a7
--- /dev/null
+++ b/lib32/safe_file_ops.c
@@ -0,0 +1 @@
+../lib/safe_file_ops.c
\ No newline at end of file
diff --git a/lib32/safe_macros.c b/lib32/safe_macros.c
new file mode 120000
index 0000000..832d7ae
--- /dev/null
+++ b/lib32/safe_macros.c
@@ -0,0 +1 @@
+../lib/safe_macros.c
\ No newline at end of file
diff --git a/lib32/safe_net.c b/lib32/safe_net.c
new file mode 120000
index 0000000..c367c2c
--- /dev/null
+++ b/lib32/safe_net.c
@@ -0,0 +1 @@
+../lib/safe_net.c
\ No newline at end of file
diff --git a/lib32/signame.h b/lib32/signame.h
new file mode 120000
index 0000000..f59345b
--- /dev/null
+++ b/lib32/signame.h
@@ -0,0 +1 @@
+../lib/signame.h
\ No newline at end of file
diff --git a/lib32/tst_ansi_color.c b/lib32/tst_ansi_color.c
new file mode 120000
index 0000000..14d8c5d
--- /dev/null
+++ b/lib32/tst_ansi_color.c
@@ -0,0 +1 @@
+../lib/tst_ansi_color.c
\ No newline at end of file
diff --git a/lib32/tst_checkpoint.c b/lib32/tst_checkpoint.c
new file mode 120000
index 0000000..28e332f
--- /dev/null
+++ b/lib32/tst_checkpoint.c
@@ -0,0 +1 @@
+../lib/tst_checkpoint.c
\ No newline at end of file
diff --git a/lib32/tst_device.c b/lib32/tst_device.c
new file mode 120000
index 0000000..f8c7982
--- /dev/null
+++ b/lib32/tst_device.c
@@ -0,0 +1 @@
+../lib/tst_device.c
\ No newline at end of file
diff --git a/lib32/tst_fill_file.c b/lib32/tst_fill_file.c
new file mode 120000
index 0000000..7439f3e
--- /dev/null
+++ b/lib32/tst_fill_file.c
@@ -0,0 +1 @@
+../lib/tst_fill_file.c
\ No newline at end of file
diff --git a/lib32/tst_kvercmp.c b/lib32/tst_kvercmp.c
new file mode 120000
index 0000000..ac15523
--- /dev/null
+++ b/lib32/tst_kvercmp.c
@@ -0,0 +1 @@
+../lib/tst_kvercmp.c
\ No newline at end of file
diff --git a/lib32/tst_mkfs.c b/lib32/tst_mkfs.c
new file mode 120000
index 0000000..a0e0421
--- /dev/null
+++ b/lib32/tst_mkfs.c
@@ -0,0 +1 @@
+../lib/tst_mkfs.c
\ No newline at end of file
diff --git a/lib32/tst_res.c b/lib32/tst_res.c
new file mode 120000
index 0000000..f2083bc
--- /dev/null
+++ b/lib32/tst_res.c
@@ -0,0 +1 @@
+../lib/tst_res.c
\ No newline at end of file
diff --git a/lib32/tst_resource.c b/lib32/tst_resource.c
new file mode 120000
index 0000000..a3c021e
--- /dev/null
+++ b/lib32/tst_resource.c
@@ -0,0 +1 @@
+../lib/tst_resource.c
\ No newline at end of file
diff --git a/lib32/tst_run_cmd.c b/lib32/tst_run_cmd.c
new file mode 120000
index 0000000..d57dbb6
--- /dev/null
+++ b/lib32/tst_run_cmd.c
@@ -0,0 +1 @@
+../lib/tst_run_cmd.c
\ No newline at end of file
diff --git a/lib32/tst_safe_macros.c b/lib32/tst_safe_macros.c
new file mode 120000
index 0000000..a1bf8c5
--- /dev/null
+++ b/lib32/tst_safe_macros.c
@@ -0,0 +1 @@
+../lib/tst_safe_macros.c
\ No newline at end of file
diff --git a/lib32/tst_test.c b/lib32/tst_test.c
new file mode 120000
index 0000000..a82ad7a
--- /dev/null
+++ b/lib32/tst_test.c
@@ -0,0 +1 @@
+../lib/tst_test.c
\ No newline at end of file
diff --git a/lib32/tst_tmpdir.c b/lib32/tst_tmpdir.c
new file mode 120000
index 0000000..a34cf42
--- /dev/null
+++ b/lib32/tst_tmpdir.c
@@ -0,0 +1 @@
+../lib/tst_tmpdir.c
\ No newline at end of file
diff --git a/m4/ltp-m32.m4 b/m4/ltp-m32.m4
new file mode 100644
index 0000000..7234415
--- /dev/null
+++ b/m4/ltp-m32.m4
@@ -0,0 +1,50 @@
+dnl Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
+dnl
+dnl This program is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU General Public License as
+dnl published by the Free Software Foundation; either version 2 of
+dnl the License, or (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it would be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write the Free Software Foundation,
+dnl Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+dnl
+
+AC_DEFUN([LTP_CHECK_CFLAGS_M32],[dnl
+
+flag="-m32"
+AC_MSG_CHECKING([if $CC supports $flag])
+
+backup_cflags="$CFLAGS"
+CFLAGS="$CFLAGS $flag"
+
+AC_LINK_IFELSE(
+	[AC_LANG_PROGRAM([])],
+	[CFLAGS_M32="$flag"]
+	[AC_MSG_RESULT([yes])],
+	[AC_MSG_RESULT([no])]
+)
+
+AC_SUBST(CFLAGS_M32)
+
+AC_MSG_CHECKING([for __sync_add_and_fetch with -m32])
+AC_LINK_IFELSE([AC_LANG_SOURCE([
+int main(void) {
+	int i = 0;
+	return __sync_add_and_fetch(&i, 1);
+}])],[has_saac="yes"])
+
+if test "x$has_saac" = xyes; then
+	AC_DEFINE(HAVE_SYNC_ADD_AND_FETCH_M32,1,[Define to 1 if you have __sync_add_and_fetch with -m32])
+	AC_MSG_RESULT(yes)
+else
+	AC_MSG_RESULT(no)
+fi
+
+CFLAGS="$backup_cflags"
+])
diff --git a/testcases/kernel/syscalls/add_key/Makefile b/testcases/kernel/syscalls/add_key/Makefile
index 2ef86f0..508e502 100644
--- a/testcases/kernel/syscalls/add_key/Makefile
+++ b/testcases/kernel/syscalls/add_key/Makefile
@@ -20,4 +20,6 @@ top_srcdir		?= ../../../..
 
 include $(top_srcdir)/include/mk/testcases.mk
 
+add_key02: CFLAGS += $(CFLAGS_M32)
+
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
-- 
2.10.2



More information about the ltp mailing list