Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/compat/linux/common Enable executing linux go binaries b...



details:   https://anonhg.NetBSD.org/src/rev/ad4995f59091
branches:  trunk
changeset: 324506:ad4995f59091
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Jul 08 17:58:39 2018 +0000

description:
Enable executing linux go binaries by using a special probe function for them.

diffstat:

 sys/compat/linux/common/linux_exec_elf32.c |  96 +++++++++++++++++++++++++++++-
 1 files changed, 94 insertions(+), 2 deletions(-)

diffs (131 lines):

diff -r 7cd804646c9c -r ad4995f59091 sys/compat/linux/common/linux_exec_elf32.c
--- a/sys/compat/linux/common/linux_exec_elf32.c        Sun Jul 08 17:58:26 2018 +0000
+++ b/sys/compat/linux/common/linux_exec_elf32.c        Sun Jul 08 17:58:39 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_exec_elf32.c,v 1.94 2017/02/06 23:45:49 uwe Exp $        */
+/*     $NetBSD: linux_exec_elf32.c,v 1.95 2018/07/08 17:58:39 christos Exp $   */
 
 /*-
  * Copyright (c) 1995, 1998, 2000, 2001 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.94 2017/02/06 23:45:49 uwe Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.95 2018/07/08 17:58:39 christos Exp $");
 
 #ifndef ELFSIZE
 /* XXX should die */
@@ -73,6 +73,8 @@
 #include <compat/linux/linux_syscallargs.h>
 #include <compat/linux/linux_syscall.h>
 
+#define LINUX_GO_RT0_SIGNATURE
+
 #ifdef DEBUG_LINUX
 #define DPRINTF(a)     uprintf a
 #else
@@ -264,6 +266,93 @@
 }
 #endif
 
+#ifdef LINUX_GO_RT0_SIGNATURE
+/*
+ * Look for a .gopclntab, specific to go binaries
+ * in it look for a symbol called _rt0_<cpu>_linux
+ */
+static int
+ELFNAME2(linux,go_rt0_signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh)
+{
+       Elf_Shdr *sh;
+       size_t shsize;
+       u_int shstrndx;
+       size_t i;
+       static const char signature[] = ".gopclntab";
+       const size_t sigsz = sizeof(signature);
+       char tbuf[sizeof(signature)], *tmp = NULL;
+       char mbuf[64];
+       const char *m;
+       int mlen;
+       int error;
+
+       /* Load the section header table. */
+       shsize = eh->e_shnum * sizeof(Elf_Shdr);
+       sh = malloc(shsize, M_TEMP, M_WAITOK);
+       error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize);
+       if (error)
+               goto out;
+
+       /* Now let's find the string table. If it does not exist, give up. */
+       shstrndx = eh->e_shstrndx;
+       if (shstrndx == SHN_UNDEF || shstrndx >= eh->e_shnum) {
+               error = ENOEXEC;
+               goto out;
+       }
+
+       /* Check if any section has the name we're looking for. */
+       const off_t stroff = sh[shstrndx].sh_offset;
+       for (i = 0; i < eh->e_shnum; i++) {
+               Elf_Shdr *s = &sh[i];
+
+               if (s->sh_name + sigsz > sh[shstrndx].sh_size)
+                       continue;
+
+               error = exec_read_from(l, epp->ep_vp, stroff + s->sh_name, tbuf,
+                   sigsz);
+               if (error)
+                       goto out;
+               if (!memcmp(tbuf, signature, sigsz)) {
+                       DPRINTF(("linux_goplcntab_sig=%s\n", tbuf);
+                       break;
+               }
+       }
+
+       if (i == eh->e_shnum) {
+               error = ENOEXEC;
+               goto out;
+       }
+
+       if (sh[i].sh_size > 1024 * 1014)
+               sh[i].sh_size = 1014 * 1014;
+
+       tmp = malloc(sh[i].sh_size, M_TEMP, M_WAITOK);
+       error = exec_read_from(l, epp->ep_vp, sh[i].sh_offset, tmp,
+           sh[i].sh_size);
+       if (error)
+               goto out;
+
+#if (ELFSIZE == 32)
+       if (strcmp(machine, "amd64") == 0)
+               m = "i386";
+       else
+               m = machine;
+#else
+       m = machine;
+#endif
+       mlen = snprintf(mbuf, sizeof(mbuf), "_rt0_%s_linux", m);
+       if (memmem(tmp, sh[i].sh_size, mbuf, mlen) == NULL)
+               error = ENOEXEC;
+       else
+               DPRINTF(("linux_rt0_sig=%s\n", mbuf));
+out:
+       if (tmp)
+               free(tmp, M_TEMP);
+       free(sh, M_TEMP);
+       return error;
+}
+#endif
+
 int
 ELFNAME2(linux,signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh, char *itp)
 {
@@ -356,6 +445,9 @@
 #ifdef LINUX_DEBUGLINK_SIGNATURE
            ((error = ELFNAME2(linux,debuglink_signature)(l, epp, eh)) != 0) &&
 #endif
+#ifdef LINUX_GO_RT0_SIGNATURE
+           ((error = ELFNAME2(linux,go_rt0_signature)(l, epp, eh)) != 0) &&
+#endif
            1) {
                        DPRINTF(("linux_probe: returning %d\n", error));
                        return error;



Home | Main Index | Thread Index | Old Index