1 /* $NetBSD: cpu_exec.c,v 1.13 2020/12/01 02:43:13 rin Exp $ */
2
3 /*-
4 * Copyright (c) 2012 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: cpu_exec.c,v 1.13 2020/12/01 02:43:13 rin Exp $");
34
35 #include "opt_compat_netbsd.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/proc.h>
40 #include <sys/exec.h>
41
42 #include <uvm/uvm_extern.h>
43
44 #include <compat/common/compat_util.h>
45 #include <sys/exec_elf.h> /* mandatory */
46
47 #include <arm/locore.h>
48
49 #if EXEC_ELF32
50 int
arm_netbsd_elf32_probe(struct lwp * l,struct exec_package * epp,void * eh0,char * itp,vaddr_t * start_p)51 arm_netbsd_elf32_probe(struct lwp *l, struct exec_package *epp, void *eh0,
52 char *itp, vaddr_t *start_p)
53 {
54 const char *itp_suffix = NULL;
55 const Elf_Ehdr * const eh = eh0;
56 const bool elf_aapcs_p =
57 (eh->e_flags & EF_ARM_EABIMASK) >= EF_ARM_EABI_VER4;
58 #if defined(COMPAT_NETBSD32) || defined(MODULAR)
59 const bool netbsd32_p = (epp->ep_esch->es_emul != &emul_netbsd);
60 #else
61 const bool netbsd32_p = false;
62 #endif
63 #ifdef __ARM_EABI__
64 const bool aapcs_p = true;
65 #else
66 const bool aapcs_p = false;
67 #endif
68 #ifdef __ARMEB__
69 const bool be8_p = (eh->e_flags & EF_ARM_BE8) != 0;
70
71 /*
72 * If the BE-8 model is supported, CPSR[7] will be clear.
73 * If the BE-32 model is supported, CPSR[7] will be set.
74 */
75 #ifdef _ARM_ARCH_BE8
76 if (!be8_p)
77 #else
78 if (be8_p)
79 #endif
80 return ENOEXEC;
81 #endif /* __ARMEB__ */
82
83 /*
84 * This is subtle. If we are netbsd32, then we don't want to match the
85 * same ABI as the kernel. If we aren't (netbsd32 == false), then we
86 * don't want to be different from the kernel's ABI.
87 * true true true ENOEXEC
88 * true false true 0
89 * true true false 0
90 * true false false ENOEXEC
91 * false true true 0
92 * false false true ENOEXEC
93 * false true false ENOEXEC
94 * false false false 0
95 */
96 if (netbsd32_p ^ elf_aapcs_p ^ aapcs_p)
97 return ENOEXEC;
98
99 if (netbsd32_p)
100 itp_suffix = (elf_aapcs_p) ? "eabi" : "oabi";
101
102 if (itp_suffix != NULL)
103 (void)compat_elf_check_interp(epp, itp, itp_suffix);
104
105 /*
106 * Copy (if any) the machine_arch of the executable to the proc.
107 */
108 if (epp->ep_machine_arch[0] != 0) {
109 strlcpy(l->l_proc->p_md.md_march, epp->ep_machine_arch,
110 sizeof(l->l_proc->p_md.md_march));
111 }
112
113 /*
114 * If we are AAPCS (EABI) and armv6/armv7, we want alignment faults
115 * to be off.
116 */
117 #if defined(__ARMEL__)
118 if (aapcs_p && (CPU_IS_ARMV7_P() || CPU_IS_ARMV6_P()))
119 #elif defined(_ARM_ARCH_BE8)
120 if (aapcs_p)
121 #else
122 if (false /* CONSTCOND */)
123 #endif
124 {
125 l->l_md.md_flags |= MDLWP_NOALIGNFLT;
126 } else {
127 l->l_md.md_flags &= ~MDLWP_NOALIGNFLT;
128 }
129 return 0;
130 }
131 #endif
132