1 1.32 maxv /* $NetBSD: setemul.c,v 1.32 2019/03/25 19:24:31 maxv Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /*- 4 1.1 jdolecek * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 1.1 jdolecek * All rights reserved. 6 1.1 jdolecek * 7 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 8 1.1 jdolecek * modification, are permitted provided that the following conditions 9 1.1 jdolecek * are met: 10 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 11 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 12 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 14 1.1 jdolecek * documentation and/or other materials provided with the distribution. 15 1.1 jdolecek * 16 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 jdolecek * POSSIBILITY OF SUCH DAMAGE. 27 1.1 jdolecek */ 28 1.1 jdolecek 29 1.1 jdolecek /* 30 1.1 jdolecek * Copyright (c) 1988, 1993 31 1.1 jdolecek * The Regents of the University of California. All rights reserved. 32 1.1 jdolecek * (c) UNIX System Laboratories, Inc. 33 1.1 jdolecek * All or some portions of this file are derived from material licensed 34 1.1 jdolecek * to the University of California by American Telephone and Telegraph 35 1.1 jdolecek * Co. or Unix System Laboratories, Inc. and are reproduced herein with 36 1.1 jdolecek * the permission of UNIX System Laboratories, Inc. 37 1.1 jdolecek * 38 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 39 1.1 jdolecek * modification, are permitted provided that the following conditions 40 1.1 jdolecek * are met: 41 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 42 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 43 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 44 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 45 1.1 jdolecek * documentation and/or other materials provided with the distribution. 46 1.15 agc * 3. Neither the name of the University nor the names of its contributors 47 1.1 jdolecek * may be used to endorse or promote products derived from this software 48 1.1 jdolecek * without specific prior written permission. 49 1.1 jdolecek * 50 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 51 1.1 jdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 1.1 jdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 1.1 jdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 54 1.1 jdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 1.1 jdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 1.1 jdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 1.1 jdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 1.1 jdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 1.1 jdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 1.1 jdolecek * SUCH DAMAGE. 61 1.1 jdolecek */ 62 1.1 jdolecek 63 1.1 jdolecek #include <sys/cdefs.h> 64 1.1 jdolecek #ifndef lint 65 1.32 maxv __RCSID("$NetBSD: setemul.c,v 1.32 2019/03/25 19:24:31 maxv Exp $"); 66 1.1 jdolecek #endif /* not lint */ 67 1.1 jdolecek 68 1.1 jdolecek #include <sys/param.h> 69 1.1 jdolecek #include <sys/errno.h> 70 1.1 jdolecek #include <sys/time.h> 71 1.20 jdolecek #include <sys/queue.h> 72 1.1 jdolecek 73 1.1 jdolecek #include <err.h> 74 1.1 jdolecek #include <stdio.h> 75 1.1 jdolecek #include <stdlib.h> 76 1.1 jdolecek #include <string.h> 77 1.1 jdolecek #include <unistd.h> 78 1.1 jdolecek #include <vis.h> 79 1.1 jdolecek 80 1.1 jdolecek #include "setemul.h" 81 1.1 jdolecek 82 1.1 jdolecek #include <sys/syscall.h> 83 1.1 jdolecek 84 1.1 jdolecek #include "../../sys/compat/netbsd32/netbsd32_syscall.h" 85 1.1 jdolecek #include "../../sys/compat/freebsd/freebsd_syscall.h" 86 1.1 jdolecek #include "../../sys/compat/linux/linux_syscall.h" 87 1.21 manu #include "../../sys/compat/linux32/linux32_syscall.h" 88 1.6 mrg #include "../../sys/compat/sunos32/sunos32_syscall.h" 89 1.1 jdolecek #include "../../sys/compat/sunos/sunos_syscall.h" 90 1.1 jdolecek #include "../../sys/compat/ultrix/ultrix_syscall.h" 91 1.22 christos #ifdef __m68k__ 92 1.22 christos #include "../../sys/compat/aoutm68k/aoutm68k_syscall.h" 93 1.22 christos #endif 94 1.1 jdolecek 95 1.1 jdolecek #define KTRACE 96 1.1 jdolecek #include "../../sys/kern/syscalls.c" 97 1.1 jdolecek 98 1.1 jdolecek #include "../../sys/compat/netbsd32/netbsd32_syscalls.c" 99 1.1 jdolecek #include "../../sys/compat/freebsd/freebsd_syscalls.c" 100 1.1 jdolecek #include "../../sys/compat/linux/linux_syscalls.c" 101 1.21 manu #include "../../sys/compat/linux32/linux32_syscalls.c" 102 1.1 jdolecek #include "../../sys/compat/sunos/sunos_syscalls.c" 103 1.6 mrg #include "../../sys/compat/sunos32/sunos32_syscalls.c" 104 1.1 jdolecek #include "../../sys/compat/ultrix/ultrix_syscalls.c" 105 1.22 christos #ifdef __m68k__ 106 1.22 christos #include "../../sys/compat/aoutm68k/aoutm68k_syscalls.c" 107 1.22 christos #endif 108 1.1 jdolecek 109 1.1 jdolecek #include "../../sys/compat/linux/common/linux_errno.c" 110 1.1 jdolecek #undef KTRACE 111 1.1 jdolecek 112 1.12 christos #define SIGRTMIN 33 /* XXX */ 113 1.12 christos #include "../../sys/compat/linux/common/linux_signo.c" 114 1.12 christos 115 1.1 jdolecek #define NELEM(a) (sizeof(a) / sizeof(a[0])) 116 1.1 jdolecek 117 1.14 manu /* static */ 118 1.14 manu const struct emulation emulations[] = { 119 1.12 christos { "netbsd", syscallnames, SYS_MAXSYSCALL, 120 1.12 christos NULL, 0, 121 1.19 mrg NULL, 0, 0 }, 122 1.12 christos 123 1.12 christos { "netbsd32", netbsd32_syscallnames, SYS_MAXSYSCALL, 124 1.12 christos NULL, 0, 125 1.19 mrg NULL, 0, EMUL_FLAG_NETBSD32 }, 126 1.12 christos 127 1.12 christos { "freebsd", freebsd_syscallnames, FREEBSD_SYS_MAXSYSCALL, 128 1.12 christos NULL, 0, 129 1.19 mrg NULL, 0, 0 }, 130 1.12 christos 131 1.12 christos { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL, 132 1.12 christos native_to_linux_errno, NELEM(native_to_linux_errno), 133 1.19 mrg linux_to_native_signo, NSIG, 0 }, 134 1.13 manu 135 1.21 manu { "linux32", linux32_syscallnames, LINUX32_SYS_MAXSYSCALL, 136 1.21 manu native_to_linux_errno, NELEM(native_to_linux_errno), 137 1.23 njoly linux_to_native_signo, NSIG, EMUL_FLAG_NETBSD32 }, 138 1.21 manu 139 1.12 christos { "sunos32", sunos32_syscallnames, SUNOS32_SYS_MAXSYSCALL, 140 1.12 christos NULL, 0, 141 1.19 mrg NULL, 0, EMUL_FLAG_NETBSD32 }, 142 1.12 christos 143 1.12 christos { "sunos", sunos_syscallnames, SUNOS_SYS_MAXSYSCALL, 144 1.12 christos NULL, 0, 145 1.19 mrg NULL, 0, 0 }, 146 1.12 christos 147 1.12 christos { "ultrix", ultrix_syscallnames, ULTRIX_SYS_MAXSYSCALL, 148 1.12 christos NULL, 0, 149 1.19 mrg NULL, 0, 0 }, 150 1.12 christos 151 1.22 christos #ifdef __m68k__ 152 1.22 christos { "aoutm68k", aoutm68k_syscallnames, AOUTM68K_SYS_MAXSYSCALL, 153 1.22 christos NULL, 0, 154 1.22 christos NULL, 0, 0 }, 155 1.22 christos #endif 156 1.22 christos 157 1.12 christos { NULL, NULL, 0, 158 1.12 christos NULL, 0, 159 1.19 mrg NULL, 0, 0 } 160 1.1 jdolecek }; 161 1.1 jdolecek 162 1.1 jdolecek struct emulation_ctx { 163 1.1 jdolecek pid_t pid; 164 1.5 jdolecek const struct emulation *emulation; 165 1.20 jdolecek LIST_ENTRY(emulation_ctx) ctx_link; 166 1.1 jdolecek }; 167 1.1 jdolecek 168 1.18 dsl const struct emulation *cur_emul; 169 1.18 dsl const struct emulation *prev_emul; 170 1.1 jdolecek 171 1.18 dsl static const struct emulation *default_emul = &emulations[0]; 172 1.1 jdolecek 173 1.1 jdolecek struct emulation_ctx *current_ctx; 174 1.20 jdolecek static LIST_HEAD(, emulation_ctx) emul_ctx = 175 1.20 jdolecek LIST_HEAD_INITIALIZER(emul_ctx); 176 1.1 jdolecek 177 1.16 christos static struct emulation_ctx *ectx_find(pid_t); 178 1.16 christos static void ectx_update(pid_t, const struct emulation *); 179 1.1 jdolecek 180 1.1 jdolecek void 181 1.16 christos setemul(const char *name, pid_t pid, int update_ectx) 182 1.1 jdolecek { 183 1.1 jdolecek int i; 184 1.5 jdolecek const struct emulation *match = NULL; 185 1.1 jdolecek 186 1.1 jdolecek for (i = 0; emulations[i].name != NULL; i++) { 187 1.1 jdolecek if (strcmp(emulations[i].name, name) == 0) { 188 1.1 jdolecek match = &emulations[i]; 189 1.1 jdolecek break; 190 1.1 jdolecek } 191 1.1 jdolecek } 192 1.1 jdolecek 193 1.1 jdolecek if (!match) { 194 1.1 jdolecek warnx("Emulation `%s' unknown", name); 195 1.1 jdolecek return; 196 1.1 jdolecek } 197 1.1 jdolecek 198 1.1 jdolecek if (update_ectx) 199 1.1 jdolecek ectx_update(pid, match); 200 1.18 dsl else 201 1.1 jdolecek default_emul = match; 202 1.7 manu 203 1.18 dsl if (cur_emul != NULL) 204 1.18 dsl prev_emul = cur_emul; 205 1.7 manu else 206 1.18 dsl prev_emul = match; 207 1.1 jdolecek 208 1.18 dsl cur_emul = match; 209 1.1 jdolecek } 210 1.1 jdolecek 211 1.1 jdolecek /* 212 1.1 jdolecek * Emulation context list is very simple chained list, not even hashed. 213 1.1 jdolecek * We expect the number of separate traced contexts/processes to be 214 1.1 jdolecek * fairly low, so it's not worth it to optimize this. 215 1.18 dsl * MMMmmmm not when I use it, it is only bounded PID_MAX! 216 1.18 dsl * Requeue looked up item at start of list to cache result since the 217 1.18 dsl * trace file tendes to have a burst of calls for a single process. 218 1.1 jdolecek */ 219 1.1 jdolecek 220 1.1 jdolecek /* 221 1.1 jdolecek * Find an emulation context appropriate for the given pid. 222 1.1 jdolecek */ 223 1.1 jdolecek static struct emulation_ctx * 224 1.16 christos ectx_find(pid_t pid) 225 1.1 jdolecek { 226 1.20 jdolecek struct emulation_ctx *ctx; 227 1.1 jdolecek 228 1.20 jdolecek /* Find an existing entry */ 229 1.20 jdolecek LIST_FOREACH(ctx, &emul_ctx, ctx_link) { 230 1.20 jdolecek if (ctx->pid == pid) 231 1.18 dsl break; 232 1.1 jdolecek } 233 1.20 jdolecek 234 1.20 jdolecek if (ctx == NULL) { 235 1.20 jdolecek /* create entry with default emulation */ 236 1.20 jdolecek ctx = malloc(sizeof *ctx); 237 1.20 jdolecek if (ctx == NULL) 238 1.20 jdolecek err(1, "malloc emul context"); 239 1.20 jdolecek ctx->pid = pid; 240 1.20 jdolecek ctx->emulation = default_emul; 241 1.20 jdolecek 242 1.20 jdolecek /* chain into the list */ 243 1.20 jdolecek LIST_INSERT_HEAD(&emul_ctx, ctx, ctx_link); 244 1.20 jdolecek } else { 245 1.20 jdolecek /* move entry to head to optimize lookup for syscall bursts */ 246 1.20 jdolecek LIST_REMOVE(ctx, ctx_link); 247 1.20 jdolecek LIST_INSERT_HEAD(&emul_ctx, ctx, ctx_link); 248 1.20 jdolecek } 249 1.20 jdolecek 250 1.18 dsl return ctx; 251 1.1 jdolecek } 252 1.1 jdolecek 253 1.1 jdolecek /* 254 1.1 jdolecek * Update emulation context for given pid, or create new if no context 255 1.1 jdolecek * for this pid exists. 256 1.1 jdolecek */ 257 1.1 jdolecek static void 258 1.16 christos ectx_update(pid_t pid, const struct emulation *emul) 259 1.1 jdolecek { 260 1.1 jdolecek struct emulation_ctx *ctx; 261 1.1 jdolecek 262 1.18 dsl ctx = ectx_find(pid); 263 1.1 jdolecek ctx->emulation = emul; 264 1.1 jdolecek } 265 1.1 jdolecek 266 1.1 jdolecek /* 267 1.1 jdolecek * Ensure current emulation context is correct for given pid. 268 1.1 jdolecek */ 269 1.1 jdolecek void 270 1.16 christos ectx_sanify(pid_t pid) 271 1.1 jdolecek { 272 1.1 jdolecek struct emulation_ctx *ctx; 273 1.1 jdolecek 274 1.18 dsl ctx = ectx_find(pid); 275 1.18 dsl cur_emul = ctx->emulation; 276 1.18 dsl } 277 1.18 dsl 278 1.18 dsl /* 279 1.18 dsl * Delete emulation context for current pid. 280 1.18 dsl * (eg when tracing exit()) 281 1.18 dsl * Defer delete just in case we've cached a pointer... 282 1.18 dsl */ 283 1.18 dsl void 284 1.18 dsl ectx_delete(void) 285 1.18 dsl { 286 1.20 jdolecek static struct emulation_ctx *ctx = NULL; 287 1.18 dsl 288 1.18 dsl if (ctx != NULL) 289 1.18 dsl free(ctx); 290 1.18 dsl 291 1.20 jdolecek /* 292 1.20 jdolecek * The emulation for current syscall entry is always on HEAD, due 293 1.20 jdolecek * to code in ectx_find(). 294 1.20 jdolecek */ 295 1.20 jdolecek ctx = LIST_FIRST(&emul_ctx); 296 1.20 jdolecek 297 1.20 jdolecek if (ctx) 298 1.20 jdolecek LIST_REMOVE(ctx, ctx_link); 299 1.14 manu } 300