1 /* $NetBSD: setemul.c,v 1.25 2007/12/31 15:26:31 ad Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 1988, 1993
31 * The Regents of the University of California. All rights reserved.
32 * (c) UNIX System Laboratories, Inc.
33 * All or some portions of this file are derived from material licensed
34 * to the University of California by American Telephone and Telegraph
35 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
36 * the permission of UNIX System Laboratories, Inc.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 #include <sys/cdefs.h>
65 __RCSID("$NetBSD: setemul.c,v 1.25 2007/12/31 15:26:31 ad Exp $");
68 #include <sys/param.h>
69 #include <sys/errno.h>
71 #include <sys/queue.h>
82 #include <sys/syscall.h>
84 #include "../../sys/compat/netbsd32/netbsd32_syscall.h"
85 #include "../../sys/compat/freebsd/freebsd_syscall.h"
86 #include "../../sys/compat/ibcs2/ibcs2_syscall.h"
87 #include "../../sys/compat/irix/irix_syscall.h"
88 #include "../../sys/compat/linux/linux_syscall.h"
89 #include "../../sys/compat/linux32/linux32_syscall.h"
90 #include "../../sys/compat/mach/mach_syscall.h"
91 #include "../../sys/compat/darwin/darwin_syscall.h"
92 #include "../../sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscall.h"
93 #include "../../sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscall.h"
94 #include "../../sys/compat/osf1/osf1_syscall.h"
95 #include "../../sys/compat/sunos32/sunos32_syscall.h"
96 #include "../../sys/compat/sunos/sunos_syscall.h"
97 #include "../../sys/compat/svr4/svr4_syscall.h"
98 #include "../../sys/compat/svr4_32/svr4_32_syscall.h"
99 #include "../../sys/compat/ultrix/ultrix_syscall.h"
101 #include "../../sys/compat/aoutm68k/aoutm68k_syscall.h"
105 #include "../../sys/kern/syscalls.c"
107 #include "../../sys/compat/netbsd32/netbsd32_syscalls.c"
108 #include "../../sys/compat/freebsd/freebsd_syscalls.c"
109 #include "../../sys/compat/ibcs2/ibcs2_syscalls.c"
110 #include "../../sys/compat/irix/irix_syscalls.c"
111 #include "../../sys/compat/linux/linux_syscalls.c"
112 #include "../../sys/compat/linux32/linux32_syscalls.c"
113 #include "../../sys/compat/darwin/darwin_syscalls.c"
114 #include "../../sys/compat/mach/mach_syscalls.c"
115 #include "../../sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscalls.c"
116 #include "../../sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscalls.c"
117 #include "../../sys/compat/osf1/osf1_syscalls.c"
118 #include "../../sys/compat/sunos/sunos_syscalls.c"
119 #include "../../sys/compat/sunos32/sunos32_syscalls.c"
120 #include "../../sys/compat/svr4/svr4_syscalls.c"
121 #include "../../sys/compat/svr4_32/svr4_32_syscalls.c"
122 #include "../../sys/compat/ultrix/ultrix_syscalls.c"
124 #include "../../sys/compat/aoutm68k/aoutm68k_syscalls.c"
127 #include "../../sys/compat/svr4/svr4_errno.c"
128 #include "../../sys/compat/ibcs2/ibcs2_errno.c"
129 #include "../../sys/compat/irix/irix_errno.c"
130 #include "../../sys/compat/osf1/osf1_errno.c"
131 #include "../../sys/compat/linux/common/linux_errno.c"
134 #define SIGRTMIN 33 /* XXX */
135 #include "../../sys/compat/svr4/svr4_signo.c"
136 #include "../../sys/compat/ibcs2/ibcs2_signo.c"
138 #include "../../sys/compat/osf1/osf1_signo.c"
139 #include "../../sys/compat/linux/common/linux_signo.c"
141 /* For Mach services names in MMSG traces */
142 #ifndef LETS_GET_SMALL
143 #include "../../sys/compat/mach/mach_services_names.c"
146 #define NELEM(a) (sizeof(a) / sizeof(a[0]))
149 const struct emulation emulations
[] = {
150 { "netbsd", syscallnames
, SYS_MAXSYSCALL
,
154 { "netbsd32", netbsd32_syscallnames
, SYS_MAXSYSCALL
,
156 NULL
, 0, EMUL_FLAG_NETBSD32
},
158 { "freebsd", freebsd_syscallnames
, FREEBSD_SYS_MAXSYSCALL
,
162 { "ibcs2", ibcs2_syscallnames
, IBCS2_SYS_MAXSYSCALL
,
163 native_to_ibcs2_errno
, NELEM(native_to_ibcs2_errno
),
164 ibcs2_to_native_signo
, NSIG
, 0 },
166 { "irix o32", irix_syscallnames
, IRIX_SYS_MAXSYSCALL
,
167 native_to_irix_errno
, NELEM(native_to_irix_errno
),
168 svr4_to_native_signo
, NSIG
, 0 },
170 { "irix n32", irix_syscallnames
, IRIX_SYS_MAXSYSCALL
,
171 native_to_irix_errno
, NELEM(native_to_irix_errno
),
172 svr4_to_native_signo
, NSIG
, 0 },
174 { "linux", linux_syscallnames
, LINUX_SYS_MAXSYSCALL
,
175 native_to_linux_errno
, NELEM(native_to_linux_errno
),
176 linux_to_native_signo
, NSIG
, 0 },
178 { "linux32", linux32_syscallnames
, LINUX32_SYS_MAXSYSCALL
,
179 native_to_linux_errno
, NELEM(native_to_linux_errno
),
180 linux_to_native_signo
, NSIG
, EMUL_FLAG_NETBSD32
},
182 { "darwin", darwin_syscallnames
, DARWIN_SYS_MAXSYSCALL
,
186 { "mach", mach_syscallnames
, MACH_SYS_MAXSYSCALL
,
190 { "mach ppccalls", mach_ppccalls_syscallnames
,
191 MACH_PPCCALLS_SYS_MAXSYSCALL
,
195 { "mach fasttraps", mach_fasttraps_syscallnames
,
196 MACH_FASTTRAPS_SYS_MAXSYSCALL
,
200 { "osf1", osf1_syscallnames
, OSF1_SYS_MAXSYSCALL
,
201 native_to_osf1_errno
, NELEM(native_to_osf1_errno
),
202 osf1_to_native_signo
, NSIG
, 0 },
204 { "sunos32", sunos32_syscallnames
, SUNOS32_SYS_MAXSYSCALL
,
206 NULL
, 0, EMUL_FLAG_NETBSD32
},
208 { "sunos", sunos_syscallnames
, SUNOS_SYS_MAXSYSCALL
,
212 { "svr4", svr4_syscallnames
, SVR4_SYS_MAXSYSCALL
,
213 native_to_svr4_errno
, NELEM(native_to_svr4_errno
),
214 svr4_to_native_signo
, NSIG
, 0 },
216 { "svr4_32", svr4_syscallnames
, SVR4_SYS_MAXSYSCALL
,
217 native_to_svr4_errno
, NELEM(native_to_svr4_errno
),
218 svr4_to_native_signo
, NSIG
, EMUL_FLAG_NETBSD32
},
220 { "ultrix", ultrix_syscallnames
, ULTRIX_SYS_MAXSYSCALL
,
224 { "pecoff", syscallnames
, SYS_MAXSYSCALL
,
229 { "aoutm68k", aoutm68k_syscallnames
, AOUTM68K_SYS_MAXSYSCALL
,
239 struct emulation_ctx
{
241 const struct emulation
*emulation
;
242 LIST_ENTRY(emulation_ctx
) ctx_link
;
245 const struct emulation
*cur_emul
;
246 const struct emulation
*prev_emul
;
247 /* Mach emulation require extra emulation contexts */
248 static const struct emulation
*mach
;
249 static const struct emulation
*mach_ppccalls
;
250 static const struct emulation
*mach_fasttraps
;
252 static const struct emulation
*default_emul
= &emulations
[0];
254 struct emulation_ctx
*current_ctx
;
255 static LIST_HEAD(, emulation_ctx
) emul_ctx
=
256 LIST_HEAD_INITIALIZER(emul_ctx
);
258 static struct emulation_ctx
*ectx_find(pid_t
);
259 static void ectx_update(pid_t
, const struct emulation
*);
262 setemul(const char *name
, pid_t pid
, int update_ectx
)
265 const struct emulation
*match
= NULL
;
267 for (i
= 0; emulations
[i
].name
!= NULL
; i
++) {
268 if (strcmp(emulations
[i
].name
, name
) == 0) {
269 match
= &emulations
[i
];
275 warnx("Emulation `%s' unknown", name
);
280 ectx_update(pid
, match
);
282 default_emul
= match
;
284 if (cur_emul
!= NULL
)
285 prev_emul
= cur_emul
;
293 * Emulation context list is very simple chained list, not even hashed.
294 * We expect the number of separate traced contexts/processes to be
295 * fairly low, so it's not worth it to optimize this.
296 * MMMmmmm not when I use it, it is only bounded PID_MAX!
297 * Requeue looked up item at start of list to cache result since the
298 * trace file tendes to have a burst of calls for a single process.
302 * Find an emulation context appropriate for the given pid.
304 static struct emulation_ctx
*
307 struct emulation_ctx
*ctx
;
309 /* Find an existing entry */
310 LIST_FOREACH(ctx
, &emul_ctx
, ctx_link
) {
316 /* create entry with default emulation */
317 ctx
= malloc(sizeof *ctx
);
319 err(1, "malloc emul context");
321 ctx
->emulation
= default_emul
;
323 /* chain into the list */
324 LIST_INSERT_HEAD(&emul_ctx
, ctx
, ctx_link
);
326 /* move entry to head to optimize lookup for syscall bursts */
327 LIST_REMOVE(ctx
, ctx_link
);
328 LIST_INSERT_HEAD(&emul_ctx
, ctx
, ctx_link
);
335 * Update emulation context for given pid, or create new if no context
336 * for this pid exists.
339 ectx_update(pid_t pid
, const struct emulation
*emul
)
341 struct emulation_ctx
*ctx
;
343 ctx
= ectx_find(pid
);
344 ctx
->emulation
= emul
;
348 * Ensure current emulation context is correct for given pid.
351 ectx_sanify(pid_t pid
)
353 struct emulation_ctx
*ctx
;
355 ctx
= ectx_find(pid
);
356 cur_emul
= ctx
->emulation
;
360 * Delete emulation context for current pid.
361 * (eg when tracing exit())
362 * Defer delete just in case we've cached a pointer...
367 static struct emulation_ctx
*ctx
= NULL
;
373 * The emulation for current syscall entry is always on HEAD, due
374 * to code in ectx_find().
376 ctx
= LIST_FIRST(&emul_ctx
);
379 LIST_REMOVE(ctx
, ctx_link
);
383 * Temporarily modify code and emulations to handle Mach traps
384 * XXX The define are duplicated from sys/arch/powerpc/include/mach_syscall.c
386 #define MACH_FASTTRAPS 0x00007ff0
387 #define MACH_PPCCALLS 0x00006000
388 #define MACH_ODD_SYSCALL_MASK 0x0000fff0
390 mach_traps_dispatch(int *code
, const struct emulation
**emul
)
392 switch (*code
& MACH_ODD_SYSCALL_MASK
) {
394 *emul
= mach_fasttraps
;
395 *code
-= MACH_FASTTRAPS
;
399 *emul
= mach_ppccalls
;
400 *code
-= MACH_PPCCALLS
;
404 if (*code
< 0 && *code
> -MACH_SYS_MAXSYSCALL
) {
414 * Lookup Machs emulations
417 mach_lookup_emul(void)
419 const struct emulation
*emul_idx
;
421 for (emul_idx
= emulations
; emul_idx
->name
; emul_idx
++) {
422 if (strcmp("mach", emul_idx
->name
) == 0)
424 if (strcmp("mach fasttraps", emul_idx
->name
) == 0)
425 mach_fasttraps
= emul_idx
;
426 if (strcmp("mach ppccalls", emul_idx
->name
) == 0)
427 mach_ppccalls
= emul_idx
;
429 if (mach
== NULL
|| mach_fasttraps
== NULL
|| mach_ppccalls
== NULL
) {
430 errx(1, "Cannot load mach emulations");
437 * Find the name of the Mach service responsible to a given message Id
440 mach_service_name(id
)
443 const char *retval
= NULL
;
444 #ifndef LETS_GET_SMALL
445 struct mach_service_name
*srv
;
447 for (srv
= mach_services_names
; srv
->srv_id
; srv
++)
448 if (srv
->srv_id
== id
)
450 retval
= srv
->srv_name
;
451 #endif /* LETS_GET_SMALL */