amd64-freebsd.c revision 294849
158551Skris/*
258551Skris * Copyright 1997 Sean Eric Fagan
358551Skris *
458551Skris * Redistribution and use in source and binary forms, with or without
558551Skris * modification, are permitted provided that the following conditions
658551Skris * are met:
7228060Sbapt * 1. Redistributions of source code must retain the above copyright
858551Skris *    notice, this list of conditions and the following disclaimer.
958551Skris * 2. Redistributions in binary form must reproduce the above copyright
1058551Skris *    notice, this list of conditions and the following disclaimer in the
1158551Skris *    documentation and/or other materials provided with the distribution.
1258551Skris * 3. All advertising materials mentioning features or use of this software
13228060Sbapt *    must display the following acknowledgement:
14228060Sbapt *	This product includes software developed by Sean Eric Fagan
1558551Skris * 4. Neither the name of the author may be used to endorse or promote
16228060Sbapt *    products derived from this software without specific prior written
17228060Sbapt *    permission.
1858551Skris *
19228060Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20228060Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2158551Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22228060Sbapt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23228060Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2458551Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25228060Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26228060Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2758551Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2858551Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2958551Skris * SUCH DAMAGE.
3058551Skris */
31228060Sbapt
32228060Sbapt#include <sys/cdefs.h>
3358551Skris__FBSDID("$FreeBSD: head/usr.bin/truss/amd64-freebsd.c 294849 2016-01-26 19:07:09Z jhb $");
34228060Sbapt
35228060Sbapt/* FreeBSD/amd64-specific system call handling. */
36228060Sbapt
37228060Sbapt#include <sys/ptrace.h>
38228060Sbapt#include <sys/syscall.h>
39228060Sbapt
4067064Sobrien#include <machine/reg.h>
4167064Sobrien#include <machine/psl.h>
4267064Sobrien
4358551Skris#include <stdio.h>
4458551Skris#include <sysdecode.h>
45
46#include "truss.h"
47
48static int
49amd64_fetch_args(struct trussinfo *trussinfo, u_int narg)
50{
51	struct ptrace_io_desc iorequest;
52	struct reg regs;
53	struct current_syscall *cs;
54	lwpid_t tid;
55	u_int i, reg;
56
57	tid = trussinfo->curthread->tid;
58	cs = &trussinfo->curthread->cs;
59	if (ptrace(PT_GETREGS, tid, (caddr_t)&regs, 0) < 0) {
60		fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
61		return (-1);
62	}
63
64	/*
65	 * FreeBSD has two special kinds of system call redirections --
66	 * SYS_syscall, and SYS___syscall.  The former is the old syscall()
67	 * routine, basically; the latter is for quad-aligned arguments.
68	 *
69	 * The system call argument count and code from ptrace() already
70	 * account for these, but we need to skip over %rax if it contains
71	 * either of these values.
72	 */
73	reg = 0;
74	switch (regs.r_rax) {
75	case SYS_syscall:
76	case SYS___syscall:
77		reg++;
78		break;
79	}
80
81	for (i = 0; i < narg && reg < 6; i++, reg++) {
82		switch (reg) {
83		case 0: cs->args[i] = regs.r_rdi; break;
84		case 1: cs->args[i] = regs.r_rsi; break;
85		case 2: cs->args[i] = regs.r_rdx; break;
86		case 3: cs->args[i] = regs.r_rcx; break;
87		case 4: cs->args[i] = regs.r_r8; break;
88		case 5: cs->args[i] = regs.r_r9; break;
89		}
90	}
91	if (narg > i) {
92		iorequest.piod_op = PIOD_READ_D;
93		iorequest.piod_offs = (void *)(regs.r_rsp + sizeof(register_t));
94		iorequest.piod_addr = &cs->args[i];
95		iorequest.piod_len = (narg - i) * sizeof(register_t);
96		ptrace(PT_IO, tid, (caddr_t)&iorequest, 0);
97		if (iorequest.piod_len == 0)
98			return (-1);
99	}
100
101	return (0);
102}
103
104static int
105amd64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
106{
107	struct reg regs;
108	lwpid_t tid;
109
110	tid = trussinfo->curthread->tid;
111	if (ptrace(PT_GETREGS, tid, (caddr_t)&regs, 0) < 0) {
112		fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
113		return (-1);
114	}
115
116	retval[0] = regs.r_rax;
117	retval[1] = regs.r_rdx;
118	*errorp = !!(regs.r_rflags & PSL_C);
119	return (0);
120}
121
122static struct procabi amd64_freebsd = {
123	"FreeBSD ELF64",
124	FREEBSD,
125	amd64_fetch_args,
126	amd64_fetch_retval
127};
128
129PROCABI(amd64_freebsd);
130