1 /* $NetBSD: setemul.c,v 1.14 2002/11/15 19:58:05 manu Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the NetBSD 18 * Foundation, Inc. and its contributors. 19 * 4. Neither the name of The NetBSD Foundation nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /* 37 * Copyright (c) 1988, 1993 38 * The Regents of the University of California. All rights reserved. 39 * (c) UNIX System Laboratories, Inc. 40 * All or some portions of this file are derived from material licensed 41 * to the University of California by American Telephone and Telegraph 42 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 43 * the permission of UNIX System Laboratories, Inc. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by the University of 56 * California, Berkeley and its contributors. 57 * 4. Neither the name of the University nor the names of its contributors 58 * may be used to endorse or promote products derived from this software 59 * without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 */ 73 74 #include <sys/cdefs.h> 75 #ifndef lint 76 __RCSID("$NetBSD: setemul.c,v 1.14 2002/11/15 19:58:05 manu Exp $"); 77 #endif /* not lint */ 78 79 #include <sys/param.h> 80 #include <sys/errno.h> 81 #include <sys/time.h> 82 83 #include <err.h> 84 #include <stdio.h> 85 #include <stdlib.h> 86 #include <string.h> 87 #include <unistd.h> 88 #include <vis.h> 89 90 #include "setemul.h" 91 92 #include <sys/syscall.h> 93 94 #include "../../sys/compat/netbsd32/netbsd32_syscall.h" 95 #include "../../sys/compat/freebsd/freebsd_syscall.h" 96 #include "../../sys/compat/hpux/hpux_syscall.h" 97 #include "../../sys/compat/ibcs2/ibcs2_syscall.h" 98 #include "../../sys/compat/irix/irix_syscall.h" 99 #include "../../sys/compat/linux/linux_syscall.h" 100 #include "../../sys/compat/mach/mach_syscall.h" 101 #include "../../sys/compat/darwin/darwin_syscall.h" 102 #include "../../sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscall.h" 103 #include "../../sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscall.h" 104 #include "../../sys/compat/osf1/osf1_syscall.h" 105 #include "../../sys/compat/sunos32/sunos32_syscall.h" 106 #include "../../sys/compat/sunos/sunos_syscall.h" 107 #include "../../sys/compat/svr4/svr4_syscall.h" 108 #include "../../sys/compat/svr4_32/svr4_32_syscall.h" 109 #include "../../sys/compat/ultrix/ultrix_syscall.h" 110 111 #define KTRACE 112 #include "../../sys/kern/syscalls.c" 113 114 #include "../../sys/compat/netbsd32/netbsd32_syscalls.c" 115 #include "../../sys/compat/freebsd/freebsd_syscalls.c" 116 #include "../../sys/compat/hpux/hpux_syscalls.c" 117 #include "../../sys/compat/ibcs2/ibcs2_syscalls.c" 118 #include "../../sys/compat/irix/irix_syscalls.c" 119 #include "../../sys/compat/linux/linux_syscalls.c" 120 #include "../../sys/compat/darwin/darwin_syscalls.c" 121 #include "../../sys/compat/mach/mach_syscalls.c" 122 #include "../../sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscalls.c" 123 #include "../../sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscalls.c" 124 #include "../../sys/compat/osf1/osf1_syscalls.c" 125 #include "../../sys/compat/sunos/sunos_syscalls.c" 126 #include "../../sys/compat/sunos32/sunos32_syscalls.c" 127 #include "../../sys/compat/svr4/svr4_syscalls.c" 128 #include "../../sys/compat/svr4_32/svr4_32_syscalls.c" 129 #include "../../sys/compat/ultrix/ultrix_syscalls.c" 130 131 #include "../../sys/compat/hpux/hpux_errno.c" 132 #include "../../sys/compat/svr4/svr4_errno.c" 133 #include "../../sys/compat/ibcs2/ibcs2_errno.c" 134 #include "../../sys/compat/irix/irix_errno.c" 135 #include "../../sys/compat/osf1/osf1_errno.c" 136 #include "../../sys/compat/linux/common/linux_errno.c" 137 #undef KTRACE 138 139 #define SIGRTMIN 33 /* XXX */ 140 #include "../../sys/compat/hpux/hpux_signo.c" 141 #include "../../sys/compat/svr4/svr4_signo.c" 142 #include "../../sys/compat/ibcs2/ibcs2_signo.c" 143 /* irix uses svr4 */ 144 #include "../../sys/compat/osf1/osf1_signo.c" 145 #include "../../sys/compat/linux/common/linux_signo.c" 146 147 #define NELEM(a) (sizeof(a) / sizeof(a[0])) 148 149 /* static */ 150 const struct emulation emulations[] = { 151 { "netbsd", syscallnames, SYS_MAXSYSCALL, 152 NULL, 0, 153 NULL, 0 }, 154 155 { "netbsd32", netbsd32_syscallnames, SYS_MAXSYSCALL, 156 NULL, 0, 157 NULL, 0 }, 158 159 { "freebsd", freebsd_syscallnames, FREEBSD_SYS_MAXSYSCALL, 160 NULL, 0, 161 NULL, 0 }, 162 163 { "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL, 164 native_to_hpux_errno, NELEM(native_to_hpux_errno), 165 hpux_to_native_signo, NSIG }, 166 167 { "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL, 168 native_to_ibcs2_errno, NELEM(native_to_ibcs2_errno), 169 ibcs2_to_native_signo, NSIG }, 170 171 { "irix o32", irix_syscallnames, IRIX_SYS_MAXSYSCALL, 172 native_to_irix_errno, NELEM(native_to_irix_errno), 173 svr4_to_native_signo, NSIG }, 174 175 { "irix n32", irix_syscallnames, IRIX_SYS_MAXSYSCALL, 176 native_to_irix_errno, NELEM(native_to_irix_errno), 177 svr4_to_native_signo, NSIG }, 178 179 { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL, 180 native_to_linux_errno, NELEM(native_to_linux_errno), 181 linux_to_native_signo, NSIG }, 182 183 { "darwin", darwin_syscallnames, DARWIN_SYS_MAXSYSCALL, 184 NULL, 0, 185 NULL, 0 }, 186 187 { "mach", mach_syscallnames, MACH_SYS_MAXSYSCALL, 188 NULL, 0, 189 NULL, 0 }, 190 191 { "mach ppccalls", mach_ppccalls_syscallnames, 192 MACH_PPCCALLS_SYS_MAXSYSCALL, 193 NULL, 0, 194 NULL, 0 }, 195 196 { "mach fasttraps", mach_fasttraps_syscallnames, 197 MACH_FASTTRAPS_SYS_MAXSYSCALL, 198 NULL, 0, 199 NULL, 0 }, 200 201 { "osf1", osf1_syscallnames, OSF1_SYS_MAXSYSCALL, 202 native_to_osf1_errno, NELEM(native_to_osf1_errno), 203 osf1_to_native_signo, NSIG }, 204 205 { "sunos32", sunos32_syscallnames, SUNOS32_SYS_MAXSYSCALL, 206 NULL, 0, 207 NULL, 0 }, 208 209 { "sunos", sunos_syscallnames, SUNOS_SYS_MAXSYSCALL, 210 NULL, 0, 211 NULL, 0 }, 212 213 { "svr4", svr4_syscallnames, SVR4_SYS_MAXSYSCALL, 214 native_to_svr4_errno, NELEM(native_to_svr4_errno), 215 svr4_to_native_signo, NSIG }, 216 217 { "svr4_32", svr4_syscallnames, SVR4_SYS_MAXSYSCALL, 218 native_to_svr4_errno, NELEM(native_to_svr4_errno), 219 svr4_to_native_signo, NSIG }, 220 221 { "ultrix", ultrix_syscallnames, ULTRIX_SYS_MAXSYSCALL, 222 NULL, 0, 223 NULL, 0 }, 224 225 { "pecoff", syscallnames, SYS_MAXSYSCALL, 226 NULL, 0, 227 NULL, 0 }, 228 229 { NULL, NULL, 0, 230 NULL, 0, 231 NULL, 0 } 232 }; 233 234 struct emulation_ctx { 235 pid_t pid; 236 const struct emulation *emulation; 237 struct emulation_ctx *next; 238 }; 239 240 const struct emulation *current; 241 const struct emulation *previous; 242 /* Mach emulation require extra emulation contexts */ 243 const struct emulation *mach; 244 const struct emulation *mach_ppccalls; 245 const struct emulation *mach_fasttraps; 246 247 static const struct emulation *default_emul=NULL; 248 249 struct emulation_ctx *current_ctx; 250 struct emulation_ctx *emul_ctx = NULL; 251 252 static struct emulation_ctx *ectx_find __P((pid_t)); 253 static void ectx_update __P((pid_t, const struct emulation *)); 254 255 void 256 setemul(name, pid, update_ectx) 257 const char *name; 258 pid_t pid; 259 int update_ectx; 260 { 261 int i; 262 const struct emulation *match = NULL; 263 264 for (i = 0; emulations[i].name != NULL; i++) { 265 if (strcmp(emulations[i].name, name) == 0) { 266 match = &emulations[i]; 267 break; 268 } 269 } 270 271 if (!match) { 272 warnx("Emulation `%s' unknown", name); 273 return; 274 } 275 276 if (update_ectx) 277 ectx_update(pid, match); 278 279 if (!default_emul) 280 default_emul = match; 281 282 if (current != NULL) 283 previous = current; 284 else 285 previous = match; 286 287 current = match; 288 } 289 290 /* 291 * Emulation context list is very simple chained list, not even hashed. 292 * We expect the number of separate traced contexts/processes to be 293 * fairly low, so it's not worth it to optimize this. 294 */ 295 296 /* 297 * Find an emulation context appropriate for the given pid. 298 */ 299 static struct emulation_ctx * 300 ectx_find(pid) 301 pid_t pid; 302 { 303 struct emulation_ctx *ctx; 304 305 for(ctx = emul_ctx; ctx != NULL; ctx = ctx->next) { 306 if (ctx->pid == pid) 307 return ctx; 308 } 309 310 return NULL; 311 } 312 313 /* 314 * Update emulation context for given pid, or create new if no context 315 * for this pid exists. 316 */ 317 static void 318 ectx_update(pid, emul) 319 pid_t pid; 320 const struct emulation *emul; 321 { 322 struct emulation_ctx *ctx; 323 324 325 if ((ctx = ectx_find(pid)) != NULL) { 326 /* found and entry, ensure the emulation is right (exec!) */ 327 ctx->emulation = emul; 328 return; 329 } 330 331 ctx = (struct emulation_ctx *)malloc(sizeof(struct emulation_ctx)); 332 ctx->pid = pid; 333 ctx->emulation = emul; 334 335 /* put the entry on start of emul_ctx chain */ 336 ctx->next = emul_ctx; 337 emul_ctx = ctx; 338 } 339 340 /* 341 * Ensure current emulation context is correct for given pid. 342 */ 343 void 344 ectx_sanify(pid) 345 pid_t pid; 346 { 347 struct emulation_ctx *ctx; 348 349 if ((ctx = ectx_find(pid)) != NULL) 350 current = ctx->emulation; 351 else if (default_emul) 352 current = default_emul; 353 else 354 current = &emulations[0]; /* NetBSD */ 355 } 356 357 /* 358 * Temporarily modify code and emulations to handle Mach traps 359 * XXX The define are duplicated from sys/arch/powerpc/include/mach_syscall.c 360 */ 361 #define MACH_FASTTRAPS 0x00007ff0 362 #define MACH_PPCCALLS 0x00006000 363 #define MACH_ODD_SYSCALL_MASK 0x0000fff0 364 int 365 mach_traps_dispatch(code, emul) 366 int *code; 367 const struct emulation **emul; 368 { 369 switch (*code & MACH_ODD_SYSCALL_MASK) { 370 case MACH_FASTTRAPS: 371 *emul = mach_fasttraps; 372 *code -= MACH_FASTTRAPS; 373 return 1; 374 break; 375 376 case MACH_PPCCALLS: 377 *emul = mach_ppccalls; 378 *code -= MACH_PPCCALLS; 379 return 1; 380 break; 381 382 default: 383 if (*code < 0) { 384 *emul = mach; 385 *code = -*code; 386 return 1; 387 } 388 break; 389 } 390 return 0; 391 } 392 393 /* 394 * Lookup Machs emulations 395 */ 396 void 397 mach_lookup_emul(void) { 398 const struct emulation *emul_idx; 399 400 for (emul_idx = emulations; emul_idx->name; emul_idx++) { 401 if (strcmp("mach", emul_idx->name) == 0) 402 mach = emul_idx; 403 if (strcmp("mach fasttraps", emul_idx->name) == 0) 404 mach_fasttraps = emul_idx; 405 if (strcmp("mach ppccalls", emul_idx->name) == 0) 406 mach_ppccalls = emul_idx; 407 } 408 if (mach == NULL || mach_fasttraps == NULL || mach_ppccalls == NULL) { 409 errx(1, "Cannot load mach emulations"); 410 exit(1); 411 } 412 return; 413 } 414