svn commit: r196601 - in stable/8/sys: . amd64/amd64
amd64/include/xen amd64/linux32 cddl/contrib/opensolaris
compat/ia32 contrib/dev/acpica contrib/pf dev/xen/xenpci
i386/i386 i386/linux kern sys
Bjoern A. Zeeb
bz at FreeBSD.org
Thu Aug 27 17:34:14 UTC 2009
Author: bz
Date: Thu Aug 27 17:34:13 2009
New Revision: 196601
URL: http://svn.freebsd.org/changeset/base/196601
Log:
MFC r196512:
Fix handling of .note.ABI-tag section for GNU systems [1].
Handle GNU/Linux according to LSB Core Specification 4.0,
Chapter 11. Object Format, 11.8. ABI note tag.
Also check the first word of desc, not only name, according to
glibc abi-tags specification to distinguish between Linux and
kFreeBSD.
Add explicit handling for Debian GNU/kFreeBSD, which runs
on our kernels as well [2].
In {amd64,i386}/trap.c, when checking osrel of the current process,
also check the ABI to not change the signal behaviour for Linux
binary processes, now that we save an osrel version for all three
from the lists above in struct proc [2].
These changes make it possible to run FreeBSD, Debian GNU/kFreeBSD
and Linux binaries on the same machine again for at least i386 and
amd64, and no longer break kFreeBSD which was detected as GNU(/Linux).
PR: kern/135468
Submitted by: dchagin [1] (initial patch)
Suggested by: kib [2]
Tested by: Petr Salinger (Petr.Salinger seznam.cz) for kFreeBSD
Reviewed by: kib
Approved by: re (kensmith)
Modified:
stable/8/sys/ (props changed)
stable/8/sys/amd64/amd64/elf_machdep.c
stable/8/sys/amd64/amd64/trap.c
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/amd64/linux32/linux32_sysvec.c
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/compat/ia32/ia32_sysvec.c
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
stable/8/sys/i386/i386/elf_machdep.c
stable/8/sys/i386/i386/trap.c
stable/8/sys/i386/linux/linux_sysvec.c
stable/8/sys/kern/imgact_elf.c
stable/8/sys/sys/imgact_elf.h
Modified: stable/8/sys/amd64/amd64/elf_machdep.c
==============================================================================
--- stable/8/sys/amd64/amd64/elf_machdep.c Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/amd64/amd64/elf_machdep.c Thu Aug 27 17:34:13 2009 (r196601)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
+#include <sys/sysent.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
@@ -108,6 +109,22 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_AN
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_oinfo);
+static Elf64_Brandinfo kfreebsd_brand_info = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_X86_64,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/lib/ld-kfreebsd-x86-64.so.1",
+ .sysvec = &elf64_freebsd_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &elf64_kfreebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(kelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &kfreebsd_brand_info);
+
void
elf64_dump_thread(struct thread *td __unused, void *dst __unused,
Modified: stable/8/sys/amd64/amd64/trap.c
==============================================================================
--- stable/8/sys/amd64/amd64/trap.c Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/amd64/amd64/trap.c Thu Aug 27 17:34:13 2009 (r196601)
@@ -409,7 +409,9 @@ trap(struct trapframe *frame)
* This check also covers the images
* without the ABI-tag ELF note.
*/
- if (p->p_osrel >= 700004) {
+ if (SV_CURPROC_ABI() ==
+ SV_ABI_FREEBSD &&
+ p->p_osrel >= 700004) {
i = SIGSEGV;
ucode = SEGV_ACCERR;
} else {
Modified: stable/8/sys/amd64/linux32/linux32_sysvec.c
==============================================================================
--- stable/8/sys/amd64/linux32/linux32_sysvec.c Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/amd64/linux32/linux32_sysvec.c Thu Aug 27 17:34:13 2009 (r196601)
@@ -127,6 +127,7 @@ static void linux_sendsig(sig_t catc
static void exec_linux_setregs(struct thread *td, u_long entry,
u_long stack, u_long ps_strings);
static void linux32_fixlimit(struct rlimit *rl, int which);
+static boolean_t linux32_trans_osrel(const Elf_Note *note, int32_t *osrel);
static eventhandler_tag linux_exit_tag;
static eventhandler_tag linux_schedtail_tag;
@@ -1066,14 +1067,38 @@ struct sysentvec elf_linux_sysvec = {
.sv_flags = SV_ABI_LINUX | SV_ILP32 | SV_IA32
};
-static char GNULINUX_ABI_VENDOR[] = "GNU";
+static char GNU_ABI_VENDOR[] = "GNU";
+static int GNULINUX_ABI_DESC = 0;
+
+static boolean_t
+linux32_trans_osrel(const Elf_Note *note, int32_t *osrel)
+{
+ const Elf32_Word *desc;
+ uintptr_t p;
+
+ p = (uintptr_t)(note + 1);
+ p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+
+ desc = (const Elf32_Word *)p;
+ if (desc[0] != GNULINUX_ABI_DESC)
+ return (FALSE);
+
+ /*
+ * For linux we encode osrel as follows (see linux_mib.c):
+ * VVVMMMIII (version, major, minor), see linux_mib.c.
+ */
+ *osrel = desc[1] * 1000000 + desc[2] * 1000 + desc[3];
+
+ return (TRUE);
+}
static Elf_Brandnote linux32_brandnote = {
- .hdr.n_namesz = sizeof(GNULINUX_ABI_VENDOR),
- .hdr.n_descsz = 16,
+ .hdr.n_namesz = sizeof(GNU_ABI_VENDOR),
+ .hdr.n_descsz = 16, /* XXX at least 16 */
.hdr.n_type = 1,
- .vendor = GNULINUX_ABI_VENDOR,
- .flags = 0
+ .vendor = GNU_ABI_VENDOR,
+ .flags = BN_TRANSLATE_OSREL,
+ .trans_osrel = linux32_trans_osrel
};
static Elf32_Brandinfo linux_brand = {
Modified: stable/8/sys/compat/ia32/ia32_sysvec.c
==============================================================================
--- stable/8/sys/compat/ia32/ia32_sysvec.c Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/compat/ia32/ia32_sysvec.c Thu Aug 27 17:34:13 2009 (r196601)
@@ -172,6 +172,21 @@ SYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY
(sysinit_cfunc_t) elf32_insert_brand_entry,
&ia32_brand_oinfo);
+static Elf32_Brandinfo kia32_brand_info = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_386,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/lib/ld.so.1",
+ .sysvec = &ia32_freebsd_sysvec,
+ .brand_note = &elf32_kfreebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(kia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &kia32_brand_info);
+
void
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
Modified: stable/8/sys/i386/i386/elf_machdep.c
==============================================================================
--- stable/8/sys/i386/i386/elf_machdep.c Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/i386/i386/elf_machdep.c Thu Aug 27 17:34:13 2009 (r196601)
@@ -108,6 +108,22 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_AN
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_oinfo);
+static Elf32_Brandinfo kfreebsd_brand_info = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_386,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/lib/ld.so.1",
+ .sysvec = &elf32_freebsd_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &elf32_kfreebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &kfreebsd_brand_info);
+
void
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
Modified: stable/8/sys/i386/i386/trap.c
==============================================================================
--- stable/8/sys/i386/i386/trap.c Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/i386/i386/trap.c Thu Aug 27 17:34:13 2009 (r196601)
@@ -423,7 +423,9 @@ trap(struct trapframe *frame)
* This check also covers the images
* without the ABI-tag ELF note.
*/
- if (p->p_osrel >= 700004) {
+ if (SV_CURPROC_ABI() ==
+ SV_ABI_FREEBSD &&
+ p->p_osrel >= 700004) {
i = SIGSEGV;
ucode = SEGV_ACCERR;
} else {
Modified: stable/8/sys/i386/linux/linux_sysvec.c
==============================================================================
--- stable/8/sys/i386/linux/linux_sysvec.c Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/i386/linux/linux_sysvec.c Thu Aug 27 17:34:13 2009 (r196601)
@@ -108,6 +108,7 @@ static void linux_sendsig(sig_t catc
static void exec_linux_setregs(struct thread *td, u_long entry,
u_long stack, u_long ps_strings);
static register_t *linux_copyout_strings(struct image_params *imgp);
+static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
static int linux_szplatform;
const char *linux_platform;
@@ -1027,14 +1028,38 @@ struct sysentvec elf_linux_sysvec = {
.sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32
};
-static char GNULINUX_ABI_VENDOR[] = "GNU";
+static char GNU_ABI_VENDOR[] = "GNU";
+static int GNULINUX_ABI_DESC = 0;
+
+static boolean_t
+linux_trans_osrel(const Elf_Note *note, int32_t *osrel)
+{
+ const Elf32_Word *desc;
+ uintptr_t p;
+
+ p = (uintptr_t)(note + 1);
+ p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+
+ desc = (const Elf32_Word *)p;
+ if (desc[0] != GNULINUX_ABI_DESC)
+ return (FALSE);
+
+ /*
+ * For linux we encode osrel as follows (see linux_mib.c):
+ * VVVMMMIII (version, major, minor), see linux_mib.c.
+ */
+ *osrel = desc[1] * 1000000 + desc[2] * 1000 + desc[3];
+
+ return (TRUE);
+}
static Elf_Brandnote linux_brandnote = {
- .hdr.n_namesz = sizeof(GNULINUX_ABI_VENDOR),
- .hdr.n_descsz = 16,
+ .hdr.n_namesz = sizeof(GNU_ABI_VENDOR),
+ .hdr.n_descsz = 16, /* XXX at least 16 */
.hdr.n_type = 1,
- .vendor = GNULINUX_ABI_VENDOR,
- .flags = 0
+ .vendor = GNU_ABI_VENDOR,
+ .flags = BN_TRANSLATE_OSREL,
+ .trans_osrel = linux_trans_osrel
};
static Elf32_Brandinfo linux_brand = {
Modified: stable/8/sys/kern/imgact_elf.c
==============================================================================
--- stable/8/sys/kern/imgact_elf.c Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/kern/imgact_elf.c Thu Aug 27 17:34:13 2009 (r196601)
@@ -86,6 +86,9 @@ static int __elfN(load_section)(struct v
vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
vm_prot_t prot, size_t pagesize);
static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp);
+static boolean_t __elfN(freebsd_trans_osrel)(const Elf_Note *note,
+ int32_t *osrel);
+static boolean_t kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel);
static boolean_t __elfN(check_note)(struct image_params *imgp,
Elf_Brandnote *checknote, int32_t *osrel);
@@ -116,9 +119,56 @@ Elf_Brandnote __elfN(freebsd_brandnote)
.hdr.n_descsz = sizeof(int32_t),
.hdr.n_type = 1,
.vendor = FREEBSD_ABI_VENDOR,
- .flags = BN_CAN_FETCH_OSREL
+ .flags = BN_TRANSLATE_OSREL,
+ .trans_osrel = __elfN(freebsd_trans_osrel)
};
+static boolean_t
+__elfN(freebsd_trans_osrel)(const Elf_Note *note, int32_t *osrel)
+{
+ uintptr_t p;
+
+ p = (uintptr_t)(note + 1);
+ p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+ *osrel = *(const int32_t *)(p);
+
+ return (TRUE);
+}
+
+static const char GNU_ABI_VENDOR[] = "GNU";
+static int GNU_KFREEBSD_ABI_DESC = 3;
+
+Elf_Brandnote __elfN(kfreebsd_brandnote) = {
+ .hdr.n_namesz = sizeof(GNU_ABI_VENDOR),
+ .hdr.n_descsz = 16, /* XXX at least 16 */
+ .hdr.n_type = 1,
+ .vendor = GNU_ABI_VENDOR,
+ .flags = BN_TRANSLATE_OSREL,
+ .trans_osrel = kfreebsd_trans_osrel
+};
+
+static boolean_t
+kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel)
+{
+ const Elf32_Word *desc;
+ uintptr_t p;
+
+ p = (uintptr_t)(note + 1);
+ p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+
+ desc = (const Elf32_Word *)p;
+ if (desc[0] != GNU_KFREEBSD_ABI_DESC)
+ return (FALSE);
+
+ /*
+ * Debian GNU/kFreeBSD embed the earliest compatible kernel version
+ * (__FreeBSD_version: <major><two digit minor>Rxx) in the LSB way.
+ */
+ *osrel = desc[1] * 100000 + desc[2] * 1000 + desc[3];
+
+ return (TRUE);
+}
+
int
__elfN(insert_brand_entry)(Elf_Brandinfo *entry)
{
@@ -1371,11 +1421,9 @@ __elfN(check_note)(struct image_params *
* Fetch the osreldate for binary
* from the ELF OSABI-note if necessary.
*/
- if ((checknote->flags & BN_CAN_FETCH_OSREL) != 0 &&
- osrel != NULL)
- *osrel = *(const int32_t *) (note_name +
- roundup2(checknote->hdr.n_namesz,
- sizeof(Elf32_Addr)));
+ if ((checknote->flags & BN_TRANSLATE_OSREL) != 0 &&
+ checknote->trans_osrel != NULL)
+ return (checknote->trans_osrel(note, osrel));
return (TRUE);
nextnote:
Modified: stable/8/sys/sys/imgact_elf.h
==============================================================================
--- stable/8/sys/sys/imgact_elf.h Thu Aug 27 17:33:44 2009 (r196600)
+++ stable/8/sys/sys/imgact_elf.h Thu Aug 27 17:34:13 2009 (r196601)
@@ -58,7 +58,10 @@ typedef struct {
Elf_Note hdr;
const char * vendor;
int flags;
-#define BN_CAN_FETCH_OSREL 0x0001
+ boolean_t (*trans_osrel)(const Elf_Note *, int32_t *);
+#define BN_CAN_FETCH_OSREL 0x0001 /* Deprecated. */
+#define BN_TRANSLATE_OSREL 0x0002 /* Use trans_osrel fetch osrel after */
+ /* checking ABI contraint if needed. */
} Elf_Brandnote;
typedef struct {
@@ -91,6 +94,7 @@ void __elfN(dump_thread)(struct thread *
extern int __elfN(fallback_brand);
extern Elf_Brandnote __elfN(freebsd_brandnote);
+extern Elf_Brandnote __elfN(kfreebsd_brandnote);
#endif /* _KERNEL */
#endif /* !_SYS_IMGACT_ELF_H_ */
More information about the svn-src-stable
mailing list