aboutsummaryrefslogtreecommitdiff
path: root/sys/i386
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2009-08-24 16:19:47 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2009-08-24 16:19:47 +0000
commit89ffc202d6864ca8a0388020b1e1e6443a16dd9a (patch)
treeb21e68a77cf9b8fa18e8b538ce504aa2bd73af12 /sys/i386
parent20cb1f56a90158c46eb215dcf1e02cfb45803520 (diff)
downloadsrc-89ffc202d6864ca8a0388020b1e1e6443a16dd9a.tar.gz
src-89ffc202d6864ca8a0388020b1e1e6443a16dd9a.zip
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 MFC after: 3 days
Notes
Notes: svn path=/head/; revision=196512
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/elf_machdep.c16
-rw-r--r--sys/i386/i386/trap.c4
-rw-r--r--sys/i386/linux/linux_sysvec.c35
3 files changed, 49 insertions, 6 deletions
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index b68a73ec3e65..a4ff9e2160b2 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -108,6 +108,22 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
(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,
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 354d791c6f40..f7064f04a537 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -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 {
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 186e14c421f8..d07f65563d31 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -108,6 +108,7 @@ static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
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 = {