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