RFC: Add 32bit x86-64 support to binutils

Robert Millan rmh@gnu.org
Thu Dec 30 21:17:00 GMT 2010


Hi folks,

I had this unsubmitted patch in my local filesystem.  It makes Linux
detect ELF32 AMD64 binaries and sets a flag to restrict them to
32-bit address space.

It's not rocket science but can save you some work in case you
haven't implemented this already.

Best regards

-- 
Robert Millan
-------------- next part --------------
diff -Nur linux-2.6-2.6.26-libre2.old/arch/x86/kernel/sys_x86_64.c linux-2.6-2.6.26-libre2/arch/x86/kernel/sys_x86_64.c
--- linux-2.6-2.6.26-libre2.old/arch/x86/kernel/sys_x86_64.c	2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/arch/x86/kernel/sys_x86_64.c	2009-05-29 22:57:41.000000000 +0200
@@ -48,7 +48,7 @@
 static void find_start_end(unsigned long flags, unsigned long *begin,
 			   unsigned long *end)
 {
-	if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
+	if ((!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) || test_thread_flag(TIF_AMD32)) {
 		unsigned long new_begin;
 		/* This is usually used needed to map code in small
 		   model, so it needs to be in the first 31bit. Limit
@@ -94,7 +94,7 @@
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32))
+	if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32) || test_thread_flag(TIF_AMD32))
 	    && len <= mm->cached_hole_size) {
 	        mm->cached_hole_size = 0;
 		mm->free_area_cache = begin;
@@ -150,8 +150,8 @@
 	if (flags & MAP_FIXED)
 		return addr;
 
-	/* for MAP_32BIT mappings we force the legact mmap base */
-	if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT))
+	/* for MAP_32BIT mappings we force the legacy mmap base */
+	if ((!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) || test_thread_flag(TIF_AMD32))
 		goto bottomup;
 
 	/* requesting a specific address */
@@ -232,5 +232,7 @@
 	up_read(&uts_sem);
 	if (personality(current->personality) == PER_LINUX32) 
 		err |= copy_to_user(&name->machine, "i686", 5); 		
+	else if (test_thread_flag(TIF_AMD32))
+		err |= copy_to_user(&name->machine, "amd32", 6);
 	return err ? -EFAULT : 0;
 }
diff -Nur linux-2.6-2.6.26-libre2.old/arch/x86/mm/mmap.c linux-2.6-2.6.26-libre2/arch/x86/mm/mmap.c
--- linux-2.6-2.6.26-libre2.old/arch/x86/mm/mmap.c	2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/arch/x86/mm/mmap.c	2009-05-26 14:30:53.000000000 +0200
@@ -53,6 +53,15 @@
 	return 0;
 }
 
+static int mmap_is_32bit(void)
+{
+	if (mmap_is_ia32 ())
+		return 1;
+	if (test_thread_flag(TIF_AMD32))
+		return 1;
+	return 0;
+}
+
 static int mmap_is_legacy(void)
 {
 	if (current->personality & ADDR_COMPAT_LAYOUT)
@@ -73,7 +82,7 @@
 	* 28 bits of randomness in 64bit mmaps, 40 address space bits
 	*/
 	if (current->flags & PF_RANDOMIZE) {
-		if (mmap_is_ia32())
+		if (mmap_is_32bit())
 			rnd = (long)get_random_int() % (1<<8);
 		else
 			rnd = (long)(get_random_int() % (1<<28));
diff -Nur linux-2.6-2.6.26-libre2.old/fs/binfmt_elf_amd32.c linux-2.6-2.6.26-libre2/fs/binfmt_elf_amd32.c
--- linux-2.6-2.6.26-libre2.old/fs/binfmt_elf_amd32.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6-2.6.26-libre2/fs/binfmt_elf_amd32.c	2009-05-26 14:26:24.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ *  Support for loading AMD32 binaries
+ *  Copyright (C) 2009  Robert Millan
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/elfcore-compat.h>
+
+#undef	ELF_CLASS
+#define	ELF_CLASS	ELFCLASS32
+
+#undef	elfhdr
+#define elfhdr		elf32_hdr
+#undef	elf_phdr
+#define elf_phdr	elf32_phdr
+#undef	elf_note
+#define elf_note	elf32_note
+#undef	elf_addr_t
+#define elf_addr_t	Elf32_Addr
+
+#undef	ELF_PLATFORM
+#define	ELF_PLATFORM	("amd32")
+
+#undef	elf_check_arch
+#define	elf_check_arch(x)	((x)->e_machine == EM_X86_64 && (x)->e_ident[EI_CLASS] == ELFCLASS32)
+
+#undef	SET_PERSONALITY
+#define SET_PERSONALITY(ex, ibcs2)	do { set_personality_64bit(); set_thread_flag(TIF_AMD32); current->personality |= force_personality32; } while (0)
+
+/* Use the generic 32-bit definition from asm/elf.h */
+#undef	ELF_ET_DYN_BASE
+#define	ELF_ET_DYN_BASE		COMPAT_ELF_ET_DYN_BASE
+
+#include "binfmt_elf.c"
diff -Nur linux-2.6-2.6.26-libre2.old/fs/Kconfig.binfmt linux-2.6-2.6.26-libre2/fs/Kconfig.binfmt
--- linux-2.6-2.6.26-libre2.old/fs/Kconfig.binfmt	2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/fs/Kconfig.binfmt	2009-05-25 00:26:10.000000000 +0200
@@ -23,6 +23,13 @@
 	  ld.so (check the file <file:Documentation/Changes> for location and
 	  latest version).
 
+config BINFMT_ELF_AMD32
+	bool "Kernel support for AMD32 binaries"
+	depends on X86_64
+	default y
+	help
+	  Support for ELF32 binaries on AMD x86-64.
+
 config COMPAT_BINFMT_ELF
 	bool
 	depends on COMPAT && MMU
diff -Nur linux-2.6-2.6.26-libre2.old/fs/Makefile linux-2.6-2.6.26-libre2/fs/Makefile
--- linux-2.6-2.6.26-libre2.old/fs/Makefile	2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/fs/Makefile	2009-05-25 00:24:37.000000000 +0200
@@ -39,6 +39,7 @@
 obj-y				+= binfmt_script.o
 
 obj-$(CONFIG_BINFMT_ELF)	+= binfmt_elf.o
+obj-$(CONFIG_BINFMT_ELF_AMD32)	+= binfmt_elf_amd32.o
 obj-$(CONFIG_COMPAT_BINFMT_ELF)	+= compat_binfmt_elf.o
 obj-$(CONFIG_BINFMT_ELF_FDPIC)	+= binfmt_elf_fdpic.o
 obj-$(CONFIG_BINFMT_SOM)	+= binfmt_som.o
diff -Nur linux-2.6-2.6.26-libre2.old/include/asm-x86/elf.h linux-2.6-2.6.26-libre2/include/asm-x86/elf.h
--- linux-2.6-2.6.26-libre2.old/include/asm-x86/elf.h	2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/include/asm-x86/elf.h	2009-05-26 14:03:51.000000000 +0200
@@ -298,7 +298,7 @@
 #define VDSO_HIGH_BASE		0xffffe000U /* CONFIG_COMPAT_VDSO address */
 
 /* 1GB for 64bit, 8MB for 32bit */
-#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
+#define STACK_RND_MASK ((test_thread_flag(TIF_IA32) || test_thread_flag(TIF_AMD32)) ? 0x7ff : 0x3fffff)
 
 #define ARCH_DLINFO							\
 do {									\
diff -Nur linux-2.6-2.6.26-libre2.old/include/asm-x86/processor.h linux-2.6-2.6.26-libre2/include/asm-x86/processor.h
--- linux-2.6-2.6.26-libre2.old/include/asm-x86/processor.h	2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/include/asm-x86/processor.h	2009-05-26 14:06:49.000000000 +0200
@@ -881,9 +881,9 @@
 #define IA32_PAGE_OFFSET	((current->personality & ADDR_LIMIT_3GB) ? \
 					0xc0000000 : 0xFFFFe000)
 
-#define TASK_SIZE		(test_thread_flag(TIF_IA32) ? \
+#define TASK_SIZE		((test_thread_flag(TIF_IA32) || test_thread_flag(TIF_AMD32)) ? \
 					IA32_PAGE_OFFSET : TASK_SIZE64)
-#define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_IA32)) ? \
+#define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_IA32) || test_tsk_thread_flag(child, TIF_AMD32)) ? \
 					IA32_PAGE_OFFSET : TASK_SIZE64)
 
 #define STACK_TOP		TASK_SIZE
diff -Nur linux-2.6-2.6.26-libre2.old/include/asm-x86/thread_info_64.h linux-2.6-2.6.26-libre2/include/asm-x86/thread_info_64.h
--- linux-2.6-2.6.26-libre2.old/include/asm-x86/thread_info_64.h	2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/include/asm-x86/thread_info_64.h	2009-05-26 14:28:33.000000000 +0200
@@ -111,8 +111,8 @@
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_MCE_NOTIFY		10	/* notify userspace of an MCE */
 #define TIF_HRTICK_RESCHED	11	/* reprogram hrtick timer */
-/* 16 free */
-#define TIF_IA32		17	/* 32bit process */
+#define TIF_AMD32		16	/* 32bit AMD process */
+#define TIF_IA32		17	/* 32bit Intel process */
 #define TIF_FORK		18	/* ret_from_fork */
 #define TIF_ABI_PENDING		19
 #define TIF_MEMDIE		20
@@ -134,6 +134,7 @@
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_MCE_NOTIFY		(1 << TIF_MCE_NOTIFY)
 #define _TIF_HRTICK_RESCHED	(1 << TIF_HRTICK_RESCHED)
+#define _TIF_AMD32		(1 << TIF_AMD32)
 #define _TIF_IA32		(1 << TIF_IA32)
 #define _TIF_FORK		(1 << TIF_FORK)
 #define _TIF_ABI_PENDING	(1 << TIF_ABI_PENDING)


More information about the Binutils mailing list