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