1188628Simp/*
2204977Simp * Copyright 1998 Sean Eric Fagan
3188628Simp *
4188628Simp * Redistribution and use in source and binary forms, with or without
5188628Simp * modification, are permitted provided that the following conditions
6188628Simp * are met:
7188628Simp * 1. Redistributions of source code must retain the above copyright
8188628Simp *    notice, this list of conditions and the following disclaimer.
9188628Simp * 2. Redistributions in binary form must reproduce the above copyright
10188628Simp *    notice, this list of conditions and the following disclaimer in the
11188628Simp *    documentation and/or other materials provided with the distribution.
12188628Simp * 3. All advertising materials mentioning features or use of this software
13188628Simp *    must display the following acknowledgement:
14188628Simp *	This product includes software developed by Sean Eric Fagan
15188628Simp * 4. Neither the name of the author may be used to endorse or promote
16188628Simp *    products derived from this software without specific prior written
17188628Simp *    permission.
18188628Simp *
19188628Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20188628Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21188628Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22188628Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23188628Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24188628Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25188628Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26188628Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27188628Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28188628Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29188628Simp * SUCH DAMAGE.
30188628Simp */
31188628Simp
32290052Sjhb#include <sys/cdefs.h>
33290052Sjhb__FBSDID("$FreeBSD$");
34188628Simp
35290052Sjhb/* FreeBSD/mips-specific system call handling. */
36188628Simp
37188628Simp#include <sys/ptrace.h>
38188628Simp#include <sys/syscall.h>
39188628Simp
40188628Simp#include <machine/frame.h>
41188628Simp#include <machine/reg.h>
42188628Simp
43188628Simp#include <stdio.h>
44188628Simp
45188628Simp#include "truss.h"
46188628Simp
47188628Simp#include "syscalls.h"
48188628Simp
49290052Sjhbstatic int
50290052Sjhbmips_fetch_args(struct trussinfo *trussinfo, u_int narg)
51240562Szont{
52240005Szont	struct ptrace_io_desc iorequest;
53240005Szont	struct reg regs;
54290052Sjhb	struct current_syscall *cs;
55240562Szont	lwpid_t tid;
56290052Sjhb	u_int i, reg;
57188628Simp
58240562Szont	tid = trussinfo->curthread->tid;
59290052Sjhb	cs = &trussinfo->curthread->cs;
60240562Szont	if (ptrace(PT_GETREGS, tid, (caddr_t)&regs, 0) < 0) {
61240005Szont		fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
62290052Sjhb		return (-1);
63240005Szont	}
64188628Simp
65290052Sjhb	/*
66290052Sjhb	 * FreeBSD has two special kinds of system call redirections --
67290052Sjhb	 * SYS_syscall, and SYS___syscall.  The former is the old syscall()
68290052Sjhb	 * routine, basically; the latter is for quad-aligned arguments.
69290052Sjhb	 *
70290052Sjhb	 * The system call argument count and code from ptrace() already
71290052Sjhb	 * account for these, but we need to skip over the first argument.
72290052Sjhb	 */
73290052Sjhb	reg = A0;
74290052Sjhb	switch (regs.r_regs[V0]) {
75290052Sjhb	case SYS_syscall:
76290052Sjhb		reg = A1;
77290052Sjhb		break;
78290052Sjhb	case SYS___syscall:
79290052Sjhb#if defined(__mips_n32) || defined(__mips_n64)
80290052Sjhb		reg = A1;
81290052Sjhb#else
82290052Sjhb		reg = A2;
83290052Sjhb#endif
84290052Sjhb		break;
85240005Szont	}
86188628Simp
87290052Sjhb#if defined(__mips_n32) || defined(__mips_n64)
88290052Sjhb#define	MAXREG		A7
89188628Simp#else
90290052Sjhb#define	MAXREG		A3
91188628Simp#endif
92188628Simp
93290052Sjhb	for (i = 0; i < narg && reg <= MAXREG; i++, reg++)
94290052Sjhb		cs->args[i] = regs.r_regs[reg];
95290052Sjhb	if (narg > i) {
96240005Szont		iorequest.piod_op = PIOD_READ_D;
97290052Sjhb		iorequest.piod_offs = (void *)((uintptr_t)regs.r_regs[SP] +
98290052Sjhb		    4 * sizeof(cs->args[0]));
99290052Sjhb		iorequest.piod_addr = &cs->args[i];
100290052Sjhb		iorequest.piod_len = (narg - i) * sizeof(cs->args[0]);
101240562Szont		ptrace(PT_IO, tid, (caddr_t)&iorequest, 0);
102240005Szont		if (iorequest.piod_len == 0)
103290052Sjhb			return (-1);
104240005Szont	}
105188628Simp
106290052Sjhb	return (0);
107188628Simp}
108188628Simp
109290052Sjhbstatic int
110290052Sjhbmips_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
111240005Szont{
112240005Szont	struct reg regs;
113240562Szont	lwpid_t tid;
114188628Simp
115240562Szont	tid = trussinfo->curthread->tid;
116240562Szont	if (ptrace(PT_GETREGS, tid, (caddr_t)&regs, 0) < 0) {
117290052Sjhb		fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
118240005Szont		return (-1);
119240005Szont	}
120188628Simp
121290052Sjhb	/* XXX: Does not have special handling for __syscall(). */
122290052Sjhb	retval[0] = regs.r_regs[V0];
123290052Sjhb	retval[1] = regs.r_regs[V1];
124290052Sjhb	*errorp = !!regs.r_regs[A3];
125290052Sjhb	return (0);
126290052Sjhb}
127240005Szont
128188628Simp
129290052Sjhbstatic struct procabi mips_fbsd = {
130290052Sjhb#ifdef __mips_n64
131290052Sjhb	"FreeBSD ELF64",
132290052Sjhb#else
133290052Sjhb	"FreeBSD ELF32",
134290052Sjhb#endif
135290052Sjhb	syscallnames,
136290052Sjhb	nitems(syscallnames),
137290052Sjhb	mips_fetch_args,
138290052Sjhb	mips_fetch_retval
139290052Sjhb};
140188628Simp
141290052SjhbPROCABI(mips_fbsd);
142