View | Details | Raw Unified | Return to bug 33300
Collapse All | Expand All

(-)conf/files.i386 (+1 lines)
Lines 352-357 Link Here
352
i386/linux/linux_locore.s	optional	compat_linux		   \
352
i386/linux/linux_locore.s	optional	compat_linux		   \
353
	dependency 	"linux_assym.h"
353
	dependency 	"linux_assym.h"
354
i386/linux/linux_machdep.c	optional	compat_linux
354
i386/linux/linux_machdep.c	optional	compat_linux
355
i386/linux/linux_ptrace.c	optional	compat_linux
355
i386/linux/linux_sysent.c	optional	compat_linux
356
i386/linux/linux_sysent.c	optional	compat_linux
356
i386/linux/linux_sysvec.c	optional	compat_linux
357
i386/linux/linux_sysvec.c	optional	compat_linux
357
svr4/imgact_svr4.c		optional	compat_svr4
358
svr4/imgact_svr4.c		optional	compat_svr4
(-)kern/sys_process.c (-1 / +1 lines)
Lines 328-334 Link Here
328
	case PT_STEP:
328
	case PT_STEP:
329
	case PT_CONTINUE:
329
	case PT_CONTINUE:
330
	case PT_DETACH:
330
	case PT_DETACH:
331
		if ((uap->req != PT_STEP) && ((unsigned)uap->data >= NSIG))
331
		if ((uap->req != PT_STEP) && ((unsigned)uap->data > _SIG_MAXSIG))
332
			return EINVAL;
332
			return EINVAL;
333
333
334
		PHOLD(p);
334
		PHOLD(p);
(-)i386/linux/linux_ptrace.c (+502 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001 Alexander Kabaev
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer 
10
 *    in this position and unchanged.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. The name of the author may not be used to endorse or promote products
15
 *    derived from this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 *
28
 * $FreeBSD:$
29
 */
30
31
#include <sys/param.h>
32
#include <sys/systm.h>
33
#include <sys/lock.h>
34
#include <sys/proc.h>
35
#include <sys/ptrace.h>
36
#include <sys/sysproto.h>
37
38
#include <machine/md_var.h>
39
#include <machine/npx.h>
40
#include <machine/reg.h>
41
42
#include <vm/vm.h>
43
#include <vm/pmap.h>
44
#include <vm/vm_map.h>
45
#include <sys/user.h>
46
47
#include <i386/linux/linux.h>
48
#include <i386/linux/linux_proto.h>
49
#include <compat/linux/linux_util.h>
50
51
/* 
52
 *   Linux ptrace requests numbers. Mostly identical to FreeBSD,
53
 *   except for MD ones and PT_ATTACH/PT_DETACH.
54
 */
55
#define	PTRACE_TRACEME		0
56
#define	PTRACE_PEEKTEXT		1
57
#define	PTRACE_PEEKDATA		2
58
#define	PTRACE_PEEKUSR		3
59
#define	PTRACE_POKETEXT		4
60
#define	PTRACE_POKEDATA		5
61
#define	PTRACE_POKEUSR		6
62
#define	PTRACE_CONT		7
63
#define	PTRACE_KILL		8
64
#define	PTRACE_SINGLESTEP	9
65
66
#define PTRACE_ATTACH		16
67
#define PTRACE_DETACH		17
68
69
#define	PTRACE_SYSCALL		24
70
71
#define PTRACE_GETREGS		12
72
#define PTRACE_SETREGS		13
73
#define PTRACE_GETFPREGS	14
74
#define PTRACE_SETFPREGS	15
75
#define PTRACE_GETFPXREGS	18
76
#define PTRACE_SETFPXREGS	19
77
78
#define PTRACE_SETOPTIONS	21
79
80
/*
81
 * Linux keeps debug registers at the following
82
 * offset in the user struct
83
 */
84
#define LINUX_DBREG_OFFSET	252
85
#define LINUX_DBREG_SIZE	8*sizeof(l_int)
86
87
static __inline__ int 
88
map_signum(int signum)
89
{
90
#ifndef __alpha__
91
	if (signum > 0 && signum <= LINUX_SIGTBLSZ)
92
		signum = linux_to_bsd_signal[_SIG_IDX(signum)];
93
#endif
94
	return ((signum == SIGSTOP)? 0 : signum);
95
}
96
97
struct linux_pt_reg {
98
	l_long	ebx;
99
	l_long	ecx;
100
	l_long	edx;
101
	l_long	esi;
102
	l_long	edi;
103
	l_long	ebp;
104
	l_long	eax;
105
	l_int	xds;
106
	l_int	xes;
107
	l_int	xfs;
108
	l_int	xgs;
109
	l_long	orig_eax;
110
	l_long	eip;
111
	l_int	xcs;
112
	l_long	eflags;
113
	l_long	esp;
114
	l_int	xss;
115
};
116
117
118
/* 
119
 *   Translate i386 ptrace registers between Linux and FreeBSD formats.
120
 *   The translation is pretty straighforward, for all registers, but
121
 *   orig_eax in Linux side and r_trapno and r_err in FreeBSD
122
 */
123
static int 
124
map_regs_to_linux(struct reg *bsd_r, struct linux_pt_reg *linux_r)
125
{
126
	linux_r->ebx = bsd_r->r_ebx;
127
	linux_r->ecx = bsd_r->r_ecx;
128
	linux_r->edx = bsd_r->r_edx;
129
	linux_r->esi = bsd_r->r_esi;
130
	linux_r->edi = bsd_r->r_edi;
131
	linux_r->ebp = bsd_r->r_ebp;
132
	linux_r->eax = bsd_r->r_eax;
133
	linux_r->xds = bsd_r->r_ds;
134
	linux_r->xes = bsd_r->r_es;
135
	linux_r->xfs = bsd_r->r_fs;
136
	linux_r->xgs = bsd_r->r_gs;
137
	linux_r->orig_eax = bsd_r->r_eax;
138
	linux_r->eip = bsd_r->r_eip;
139
	linux_r->xcs = bsd_r->r_cs;
140
	linux_r->eflags = bsd_r->r_eflags;
141
	linux_r->esp = bsd_r->r_esp;
142
	linux_r->xss = bsd_r->r_ss;
143
	return (0);
144
}
145
146
static int 
147
map_regs_from_linux(struct reg *bsd_r, struct linux_pt_reg *linux_r)
148
{
149
	bsd_r->r_ebx = linux_r->ebx;
150
	bsd_r->r_ecx = linux_r->ecx;
151
	bsd_r->r_edx = linux_r->edx;
152
	bsd_r->r_esi = linux_r->esi;
153
	bsd_r->r_edi = linux_r->edi;
154
	bsd_r->r_ebp = linux_r->ebp;
155
	bsd_r->r_eax = linux_r->eax;
156
	bsd_r->r_ds  = linux_r->xds;
157
	bsd_r->r_es  = linux_r->xes;
158
	bsd_r->r_fs  = linux_r->xfs;
159
	bsd_r->r_gs  = linux_r->xgs;
160
	bsd_r->r_eip = linux_r->eip;
161
	bsd_r->r_cs  = linux_r->xcs;
162
	bsd_r->r_eflags = linux_r->eflags;
163
	bsd_r->r_esp = linux_r->esp;
164
	bsd_r->r_ss = linux_r->xss;
165
	return (0);
166
}
167
168
struct linux_pt_fpreg {
169
	l_long cwd;
170
	l_long swd;
171
	l_long twd;
172
	l_long fip;
173
	l_long fcs;
174
	l_long foo;
175
	l_long fos;
176
	l_long st_space[2*10];
177
};
178
179
static int 
180
map_fpregs_to_linux(struct fpreg *bsd_r, struct linux_pt_fpreg *linux_r)
181
{
182
	linux_r->cwd = bsd_r->fpr_env[0];
183
	linux_r->swd = bsd_r->fpr_env[1];
184
	linux_r->twd = bsd_r->fpr_env[2];
185
	linux_r->fip = bsd_r->fpr_env[3];
186
	linux_r->fcs = bsd_r->fpr_env[4];
187
	linux_r->foo = bsd_r->fpr_env[5];
188
	linux_r->fos = bsd_r->fpr_env[6];
189
	bcopy(bsd_r->fpr_acc, linux_r->st_space, sizeof(linux_r->st_space));
190
	return (0);
191
}
192
193
static int 
194
map_fpregs_from_linux(struct fpreg *bsd_r, struct linux_pt_fpreg *linux_r)
195
{
196
	bsd_r->fpr_env[0] = linux_r->cwd;
197
	bsd_r->fpr_env[1] = linux_r->swd;
198
	bsd_r->fpr_env[2] = linux_r->twd;
199
	bsd_r->fpr_env[3] = linux_r->fip;
200
	bsd_r->fpr_env[4] = linux_r->fcs;
201
	bsd_r->fpr_env[5] = linux_r->foo;
202
	bsd_r->fpr_env[6] = linux_r->fos;
203
	bcopy(bsd_r->fpr_acc, linux_r->st_space, sizeof(bsd_r->fpr_acc));
204
	return (0);
205
}
206
207
struct linux_pt_fpxreg {
208
	l_ushort	cwd;
209
	l_ushort	swd;
210
	l_ushort	twd;
211
	l_ushort	fop;
212
	l_long		fip;
213
	l_long		fcs;
214
	l_long		foo;
215
	l_long		fos;
216
	l_long		mxcsr;
217
	l_long		reserved;
218
	l_long		st_space[32];
219
	l_long		xmm_space[32];
220
	l_long		padding[56];
221
};
222
223
static int 
224
linux_proc_read_fpxregs(struct proc *p, struct linux_pt_fpxreg *fpxregs) 
225
{
226
#ifdef CPU_ENABLE_SSE
227
	if (sizeof(*fpxregs) != sizeof(p->p_addr->u_pcb.pcb_save.sv_xmm)) {
228
		printf("linux: savexmm != linux_pt_fpxreg\n");
229
		return (EIO);
230
	}
231
	if (cpu_fxsr == 0)
232
#endif
233
		return (EIO);
234
	bcopy(&p->p_addr->u_pcb.pcb_save.sv_xmm, fpxregs, sizeof *fpxregs);
235
	return (0);
236
}
237
238
static int 
239
linux_proc_write_fpxregs(struct proc *p, struct linux_pt_fpxreg *fpxregs)
240
{
241
#ifdef CPU_ENABLE_SSE
242
	if (sizeof(*fpxregs) != sizeof(p->p_addr->u_pcb.pcb_save.sv_xmm)) {
243
		printf("linux: savexmm != linux_pt_fpxreg\n");
244
		return (EIO);
245
	}
246
	if (cpu_fxsr == 0)
247
#endif
248
		return (EIO);
249
	bcopy(fpxregs, &p->p_addr->u_pcb.pcb_save.sv_xmm, sizeof *fpxregs);
250
	return (0);
251
}
252
253
254
int
255
linux_ptrace(struct proc *p, struct linux_ptrace_args *uap)
256
{
257
	struct ptrace_args bsd_args;
258
	int	error;
259
	caddr_t	sg;
260
	union {
261
		struct linux_pt_reg	reg;
262
		struct linux_pt_fpreg	fpreg;
263
		struct linux_pt_fpxreg	fpxreg;
264
	} r;
265
266
	sg = stackgap_init();
267
268
	error = 0;
269
270
	/* by default, just copy data intact */
271
	bsd_args.req  = uap->req;
272
	bsd_args.pid  = (pid_t)uap->pid;
273
	bsd_args.addr = (caddr_t)uap->addr;
274
	bsd_args.data = uap->data;
275
276
	switch (uap->req) {
277
	case PTRACE_TRACEME:
278
	case PTRACE_POKETEXT:
279
	case PTRACE_POKEDATA:
280
	case PTRACE_KILL:
281
		error = ptrace(p, &bsd_args);
282
		break;
283
	case PTRACE_PEEKTEXT:
284
	case PTRACE_PEEKDATA: {
285
		/* need to preserve return value */
286
		int rval = p->p_retval[0];
287
		bsd_args.data = 0;
288
		error = ptrace(p, &bsd_args);
289
		if (error == 0)
290
			error = copyout(p->p_retval,
291
			    (caddr_t)uap->data, sizeof(l_int));
292
		p->p_retval[0] = rval;
293
		break;
294
	}
295
	case PTRACE_DETACH:
296
		bsd_args.req = PT_DETACH;
297
		/* fall through */
298
	case PTRACE_SINGLESTEP:
299
	case PTRACE_CONT:
300
		bsd_args.data = map_signum(uap->data);
301
		bsd_args.addr = (caddr_t)1;
302
		error = ptrace(p, &bsd_args);
303
		break;
304
	case PTRACE_ATTACH:
305
		bsd_args.req = PT_ATTACH;
306
		error = ptrace(p, &bsd_args);
307
		break;
308
	case PTRACE_GETREGS: {
309
		struct reg *bsd_r = (struct reg*)stackgap_alloc(&sg,
310
                    sizeof(*bsd_r));
311
		/* Linux is using data where FreeBSD is using addr */
312
		bsd_args.req  = PT_GETREGS;
313
		bsd_args.addr = (caddr_t)bsd_r;
314
		bsd_args.data = 0;
315
		error = ptrace(p, &bsd_args);
316
		if (error == 0)
317
			error = map_regs_to_linux(bsd_r, &r.reg);
318
		if (error == 0)
319
			error = copyout(&r.reg, (caddr_t)uap->data, sizeof r.reg);
320
		break;
321
	}
322
	case PTRACE_SETREGS: {
323
		struct reg *bsd_r = (struct reg*)stackgap_alloc(&sg,
324
                    sizeof(*bsd_r));
325
		/* Linux is using data where FreeBSD is using addr */
326
		bsd_args.req  = PT_SETREGS;
327
		bsd_args.addr = (caddr_t)bsd_r;
328
		bsd_args.data = 0;
329
		error = copyin((caddr_t)uap->data, &r.reg, sizeof r.reg);
330
		if (error == 0)
331
			error = map_regs_from_linux(bsd_r, &r.reg);
332
		if (error == 0)
333
			error = ptrace(p, &bsd_args);
334
		break;
335
	}
336
	case PTRACE_GETFPREGS: {
337
		struct fpreg *bsd_r = (struct fpreg*)stackgap_alloc(&sg,
338
                    sizeof(*bsd_r));
339
		/* Linux is using data where FreeBSD is using addr */
340
		bsd_args.req  = PT_GETFPREGS;
341
		bsd_args.addr = (caddr_t)bsd_r;
342
		bsd_args.data = 0;
343
		error = ptrace(p, &bsd_args);
344
		if (error == 0)
345
			error = map_fpregs_to_linux(bsd_r, &r.fpreg);
346
		if (error == 0)
347
			error = copyout(&r.fpreg, (caddr_t)uap->data, sizeof r.fpreg);
348
		break;
349
	}
350
	case PTRACE_SETFPREGS: {
351
		struct fpreg *bsd_r = (struct fpreg*)stackgap_alloc(&sg,
352
                    sizeof(*bsd_r));
353
		/* Linux is using data where FreeBSD is using addr */
354
		bsd_args.req  = PT_SETFPREGS;
355
		bsd_args.addr = (caddr_t)bsd_r;
356
		bsd_args.data = 0;
357
		error = copyin((caddr_t)uap->data, &r.fpreg, sizeof r.fpreg);
358
		if (error == 0)
359
			error = map_fpregs_from_linux(bsd_r, &r.fpreg);
360
		if (error == 0)
361
			error = ptrace(p, &bsd_args);
362
		break;
363
	}
364
	case PTRACE_SETFPXREGS:
365
	case PTRACE_GETFPXREGS: {
366
		struct proc *pchild;
367
		struct fpreg *bsd_r;
368
369
		/*
370
		 * Use FreeBSD PT_GETFPREGS for permisson testing.
371
		 */
372
		bsd_r = (struct fpreg*)stackgap_alloc(&sg,
373
                    sizeof(*bsd_r));
374
		bsd_args.req  = PT_GETFPREGS;
375
		bsd_args.addr = (caddr_t)bsd_r;
376
		bsd_args.data = 0;
377
		error = ptrace(p, &bsd_args);
378
		/*
379
		 * If this fails, PTRACE_GETFPXREGS should fail
380
		 * for exactly the same reason. 
381
		*/
382
		if (error != 0) 			     
383
			break;
384
385
		if ((pchild = pfind(uap->pid)) == NULL) {
386
			error = ESRCH;
387
			break;
388
		}
389
		if (uap->req == PTRACE_GETFPXREGS) {
390
			PHOLD(pchild);
391
			error = linux_proc_read_fpxregs(
392
				pchild, &r.fpxreg);
393
			PRELE(pchild);
394
			if (error == 0)
395
				error = copyout(&r.fpxreg,
396
				    (caddr_t)uap->data, sizeof r.fpxreg);
397
		} else {
398
			error = copyin((caddr_t)uap->data,
399
			    &r.fpxreg, sizeof r.fpxreg);
400
			if (error == 0) {
401
				/* clear dangerous bits exactly as Linux does*/
402
				r.fpxreg.mxcsr &= 0xffbf;
403
				PHOLD(pchild);
404
				error = linux_proc_write_fpxregs(
405
					pchild, &r.fpxreg);
406
				PRELE(pchild);
407
			}
408
		}
409
		break;
410
	}
411
	case PTRACE_PEEKUSR:
412
	case PTRACE_POKEUSR: {
413
		error = EIO;
414
415
		/* check addr for alignment */
416
		if (uap->addr < 0 || uap->addr & (sizeof(l_int) - 1))
417
			break;
418
		/* 
419
		 * Allow linux programs to access register values in
420
		 * user struct. We simulate this through PT_GET/SETREGS
421
		 * as necessary.
422
		 */
423
		if (uap->addr < sizeof(struct linux_pt_reg)) {
424
			struct reg *bsd_r;
425
426
			bsd_r = (struct reg*)stackgap_alloc(&sg,
427
			    sizeof(*bsd_r));
428
			bsd_args.req  = PT_GETREGS;
429
			bsd_args.addr = (caddr_t)bsd_r;
430
			bsd_args.data = 0;
431
432
			error = ptrace(p, &bsd_args);
433
			if (error != 0)
434
				break;
435
			
436
			error = map_regs_to_linux(bsd_r, &r.reg);
437
			if (error != 0)
438
				break;
439
440
			if (uap->req == PTRACE_PEEKUSR) {
441
				error = copyout((char *)&r.reg + uap->addr,
442
				    (caddr_t)uap->data, sizeof(l_int));
443
				break;
444
			}
445
446
			*(l_int *)((char *)&r.reg + uap->addr) = (l_int)uap->data;
447
448
			error = map_regs_from_linux(bsd_r, &r.reg);
449
			if (error != 0)
450
				break;
451
452
			bsd_args.req  = PT_SETREGS;
453
			bsd_args.addr = (caddr_t)bsd_r;
454
			bsd_args.data = 0;
455
			error = ptrace(p, &bsd_args);
456
		}
457
		
458
		/* 
459
		 * Simulate debug registers access
460
		 */
461
		if (uap->addr >= LINUX_DBREG_OFFSET && 
462
		    uap->addr <= LINUX_DBREG_OFFSET + LINUX_DBREG_SIZE) {
463
			struct dbreg *bsd_r;
464
465
			bsd_r = (struct dbreg*)stackgap_alloc(&sg,
466
			    sizeof(*bsd_r));
467
			bsd_args.req  = PT_GETDBREGS;
468
			bsd_args.addr = (caddr_t)bsd_r;
469
			bsd_args.data = 0;
470
			error = ptrace(p, &bsd_args);
471
			if (error != 0)
472
				break;
473
			
474
			uap->addr -= LINUX_DBREG_OFFSET;
475
			if (uap->req == PTRACE_PEEKUSR) {
476
				error = copyout((char *)bsd_r + uap->addr,
477
				    (caddr_t)uap->data, sizeof(l_int));
478
				break;
479
			}
480
481
			*(l_int *)((char *)bsd_r + uap->addr) = uap->data;
482
			bsd_args.req  = PT_SETDBREGS;
483
			bsd_args.addr = (caddr_t)bsd_r;
484
			bsd_args.data = 0;
485
			error = ptrace(p, &bsd_args);
486
		}
487
488
		break;
489
	}
490
	case PTRACE_SYSCALL:
491
		/* fall through */
492
	default:
493
		error = EINVAL;
494
		goto noimpl;
495
	}
496
	return (error);
497
498
 noimpl:
499
	printf("linux: ptrace(%u, ...) not implemented\n",
500
	    (u_int32_t)uap->req);
501
	return (error);
502
}
(-)i386/linux/linux_dummy.c (-1 lines)
Lines 39-45 Link Here
39
DUMMY(stat);
39
DUMMY(stat);
40
DUMMY(mount);
40
DUMMY(mount);
41
DUMMY(stime);
41
DUMMY(stime);
42
DUMMY(ptrace);
43
DUMMY(fstat);
42
DUMMY(fstat);
44
DUMMY(olduname);
43
DUMMY(olduname);
45
DUMMY(syslog);
44
DUMMY(syslog);
(-)i386/linux/syscalls.master (-1 / +2 lines)
Lines 65-71 Link Here
65
23	STD	LINUX	{ int linux_setuid16(l_uid16_t uid); }
65
23	STD	LINUX	{ int linux_setuid16(l_uid16_t uid); }
66
24	STD	LINUX	{ int linux_getuid16(void); }
66
24	STD	LINUX	{ int linux_getuid16(void); }
67
25	STD	LINUX	{ int linux_stime(void); }
67
25	STD	LINUX	{ int linux_stime(void); }
68
26	STD	LINUX	{ int linux_ptrace(void); }
68
26	STD	LINUX	{ int linux_ptrace(l_long req, l_long pid, l_long addr, \
69
                            l_long data); }
69
27	STD	LINUX	{ int linux_alarm(l_uint secs); }
70
27	STD	LINUX	{ int linux_alarm(l_uint secs); }
70
28	STD	LINUX	{ int linux_fstat(l_uint fd, struct ostat *up); }
71
28	STD	LINUX	{ int linux_fstat(l_uint fd, struct ostat *up); }
71
29	STD	LINUX	{ int linux_pause(void); }
72
29	STD	LINUX	{ int linux_pause(void); }
(-)modules/linux/Makefile (-1 / +3 lines)
Lines 8-14 Link Here
8
SRCS=	linux_dummy.c linux_file.c linux_getcwd.c linux_ioctl.c linux_ipc.c \
8
SRCS=	linux_dummy.c linux_file.c linux_getcwd.c linux_ioctl.c linux_ipc.c \
9
	linux_machdep.c linux_mib.c linux_misc.c linux_signal.c linux_socket.c \
9
	linux_machdep.c linux_mib.c linux_misc.c linux_signal.c linux_socket.c \
10
	linux_stats.c linux_sysctl.c linux_sysent.c linux_sysvec.c \
10
	linux_stats.c linux_sysctl.c linux_sysent.c linux_sysvec.c \
11
	linux_util.c opt_compat.h opt_linux.h opt_vmpage.h vnode_if.h
11
	linux_util.c linux_ptrace.c opt_compat.h opt_linux.h opt_vmpage.h \
12
	vnode_if.h
13
12
OBJS=	linux_locore.o
14
OBJS=	linux_locore.o
13
MAN=	linux.8
15
MAN=	linux.8

Return to bug 33300