lib32: Add support for linking 32bit programs on 64bit
RFC PATCH v2 1/1 lib32: Add support for linking 32bit programs on 64bit
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
---
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
configure.ac +1 -0
@@ -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
include/mk/config.mk.in +2 -0
@@ -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@
include/mk/env_post.mk +19 -2
@@ -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
include/mk/testcases.mk +9 -0
@@ -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)
include/tst_atomic.h +2 -1
@@ -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);
lib32/Makefile new file +53 -0
53 lines not on this page · raw message
lib32/errnos.h new file +1 -0
@@ -0,0 +1 @@ +../lib/errnos.h
lib32/safe_file_ops.c new file +1 -0
@@ -0,0 +1 @@ +../lib/safe_file_ops.c
lib32/safe_macros.c new file +1 -0
@@ -0,0 +1 @@ +../lib/safe_macros.c
lib32/safe_net.c new file +1 -0
@@ -0,0 +1 @@ +../lib/safe_net.c
lib32/signame.h new file +1 -0
@@ -0,0 +1 @@ +../lib/signame.h
lib32/tst_ansi_color.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_ansi_color.c
lib32/tst_checkpoint.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_checkpoint.c
lib32/tst_device.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_device.c
lib32/tst_fill_file.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_fill_file.c
lib32/tst_kvercmp.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_kvercmp.c
lib32/tst_mkfs.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_mkfs.c
lib32/tst_res.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_res.c
lib32/tst_resource.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_resource.c
lib32/tst_run_cmd.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_run_cmd.c
lib32/tst_safe_macros.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_safe_macros.c
lib32/tst_test.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_test.c
lib32/tst_tmpdir.c new file +1 -0
@@ -0,0 +1 @@ +../lib/tst_tmpdir.c
m4/ltp-m32.m4 new file +50 -0
50 lines not on this page · raw message
testcases/kernel/syscalls/add_key/Makefile +2 -0
@@ -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
Signature · 1 line
2.10.2
RFC PATCH v2 1/1 lib32: Add support for linking 32bit programs on 64bit
include/mk/env_post.mk MAKE_TARGETS := $(filter-out $(FILTER_OUT_MAKE_TARGETS),$(MAKE_TARGETS)) · line 74
Quoted 5 lines · On Thu, 6 Apr 2017 14:46:41 +0200 "Cyril Hrubis" <[email protected]> wrote:
include/mk/env_post.mk +5
-0+ifeq ($(filter -m32,$(CFLAGS)),) +$(MAKE_TARGETS): LDFLAGS += -L$(top_builddir)/lib$(subst -m,,$(filter -m32,$(CFLAGS))) +else +LDFLAGS += -L$(top_builddir)/lib +endif
I think this breaks the build if you do 'make CFLAGS+=-m32' or './configure CFLAGS=-m32' to build everything in compatability mode. Am I doing it wrong or is this an issue?
lib32/Makefile line 19
Quoted 5 lines
lib32/Makefile new file +5
-0+# +# 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. +#
Minor nit: should be e-mail.
m4/ltp-m32.m4 line 16
Quoted 5 lines
m4/ltp-m32.m4 new file +5
-0+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
Again, e-mail.
Tested it on 64-bit Tumbleweed and 32-bit SLES11. It works fine except for issue mentioned above. I can't comment on whether the approach is correct.
Thank you,
Richard.
RFC PATCH v2 1/1 lib32: Add support for linking 32bit programs on 64bit
Hi!
Quoted 9 lines
include/mk/env_post.mk MAKE_TARGETS := $(filter-out $(FILTER_OUT_MAKE_TARGETS),$(MAKE_TARGETS)) · line 74
Quoted 5 lines
include/mk/env_post.mk +5
-0+ifeq ($(filter -m32,$(CFLAGS)),) +$(MAKE_TARGETS): LDFLAGS += -L$(top_builddir)/lib$(subst -m,,$(filter -m32,$(CFLAGS))) +else +LDFLAGS += -L$(top_builddir)/lib +endifI think this breaks the build if you do 'make CFLAGS+=-m32' or './configure CFLAGS=-m32' to build everything in compatability mode. Am I doing it wrong or is this an issue?
If -m32 is in CFLAGS the $(filter -m32,$(CFLAGS)) is nonempty and we will add -L$(top_builddir)/lib regardless. We will build the lib32 as well but never use it.
And you have to pass LDLAGS=-m32 to the configure script as well, since the implicit rule to build an executable from list of object files is:
$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
Hence if you pass -m32 only to CFLAGS the compiler will fail to link the ltp-pan binary.
Passing -m32 in CFLAGS only works for testcases though, since they are compiled and linked in one try and hence use both LDFLAGS and CFLAGS.
Quoted 7 lines
lib32/Makefile line 19
Quoted 5 lines
lib32/Makefile new file +5
-0+# +# 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. +#Minor nit: should be e-mail.
Ok. I guess that we should use recent enough headers...
Signature · 2 lines
Cyril Hrubis [email protected]
RFC PATCH v2 1/1 lib32: Add support for linking 32bit programs on 64bit
Hi,
Quoted 18 lines · On Fri, 7 Apr 2017 11:19:45 +0200 "Cyril Hrubis" <[email protected]> wrote:
Hi!
Quoted 9 lines
include/mk/env_post.mk MAKE_TARGETS := $(filter-out $(FILTER_OUT_MAKE_TARGETS),$(MAKE_TARGETS)) · line 74
Quoted 5 lines
include/mk/env_post.mk +5
-0+ifeq ($(filter -m32,$(CFLAGS)),) +$(MAKE_TARGETS): LDFLAGS += -L$(top_builddir)/lib$(subst -m,,$(filter -m32,$(CFLAGS))) +else +LDFLAGS += -L$(top_builddir)/lib +endifI think this breaks the build if you do 'make CFLAGS+=-m32' or './configure CFLAGS=-m32' to build everything in compatability mode. Am I doing it wrong or is this an issue?
If -m32 is in CFLAGS the $(filter -m32,$(CFLAGS)) is nonempty and we will add -L$(top_builddir)/lib regardless. We will build the lib32 as well but never use it.
And you have to pass LDLAGS=-m32 to the configure script as well, since the implicit rule to build an executable from list of object files is:
Quoted 8 lines
$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
Hence if you pass -m32 only to CFLAGS the compiler will fail to link the ltp-pan binary.
Passing -m32 in CFLAGS only works for testcases though, since they are compiled and linked in one try and hence use both LDFLAGS and CFLAGS.
OK, makes sense.
Build still fails however, because of missing 32-bit libraries, but that is just because the headers are present for the 64-bit lib and a lot of tests will try to build so long as the headers are there. I guess it would be better to also check that we can link as well, which some tests appear to do. I think it is quite a reasonable workaround to just install the libs though assuming that they will all usually be available if any 32-bit libs are.
Thank you,
Richard.
RFC PATCH v2 1/1 lib32: Add support for linking 32bit programs on 64bit
Hi!
Quoted 6 lines
Build still fails however, because of missing 32-bit libraries, but that is just because the headers are present for the 64-bit lib and a lot of tests will try to build so long as the headers are there. I guess it would be better to also check that we can link as well, which some tests appear to do. I think it is quite a reasonable workaround to just install the libs though assuming that they will all usually be available if any 32-bit libs are.
We may try to fix the build system to try linking with the libraries as well but that is unrelated problem that is there from the start.
Signature · 2 lines
Cyril Hrubis [email protected]
RFC PATCH v2 1/1 lib32: Add support for linking 32bit programs on 64bit
In reply to Cyril HrubisHi,
Quoted 12 lines · Cyril Hrubis
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.hotherwise)* The directory lib32 contains symlinks of minimal set of sources needed to link newlib testcase +
Makefile.
Quoted 6 lines
* 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
I'm not sure if this has already been taken into account, but on aarch64 gcc does not recognise the -m32 switch and compilation fails if the test case has added -m32 to its CFLAGS.
Signature · 2 lines
Thank you, Richard.
RFC PATCH v2 1/1 lib32: Add support for linking 32bit programs on 64bit
In reply to Cyril HrubisQuoted 1 line · Cyril Hrubis
This is proof of concept for building 32bit testcases on 64bit platform.
Not sure if LTP is supposed to run on these or if lib32 accounts for them, just letting you know that they exist (and if the code doesn't support them and adding support is easy, you might want to consider it):
* IBM System z (S390) has 31bit mode, not 32bit and the corresponding gcc flag is -m31, not -m32
* Some distros (ie. RHEL5 on PPC) have 32bit userspace by default, but have a secondary 64bit userspace mode - here, both -m32 and -m64 work, just the default is not -m64
* Some distros use the x32 ABI for userspace, -mx32, still being 32bit, but not -m32
Jiri