1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <sys/stack.h>
27#include <sys/regset.h>
28#include <sys/frame.h>
29#include <sys/sysmacros.h>
30#include <sys/trap.h>
31#include <sys/machelf.h>
32
33#include <stdlib.h>
34#include <unistd.h>
35#include <sys/types.h>
36#include <errno.h>
37#include <string.h>
38
39#include "Pcontrol.h"
40#include "Pstack.h"
41
42static uchar_t int_syscall_instr[] = { 0xCD, T_SYSCALLINT };
43
44const char *
45Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
46{
47	map_info_t *mp = Paddr2mptr(P, pltaddr);
48
49	uintptr_t r_addr;
50	file_info_t *fp;
51	Elf32_Rel r;
52	size_t i;
53
54	if (mp == NULL || (fp = mp->map_file) == NULL ||
55	    fp->file_plt_base == 0 ||
56	    pltaddr - fp->file_plt_base >= fp->file_plt_size) {
57		errno = EINVAL;
58		return (NULL);
59	}
60
61	i = (pltaddr - fp->file_plt_base) / M_PLT_ENTSIZE - M_PLT_XNumber;
62
63	r_addr = fp->file_jmp_rel + i * sizeof (r);
64
65	if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
66	    (i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
67
68		Elf_Data *data = fp->file_dynsym.sym_data_pri;
69		Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);
70
71		return (fp->file_dynsym.sym_strs + symp->st_name);
72	}
73
74	return (NULL);
75}
76
77int
78Pissyscall(struct ps_prochandle *P, uintptr_t addr)
79{
80	uchar_t instr[16];
81
82	if (Pread(P, instr, sizeof (int_syscall_instr), addr) !=
83	    sizeof (int_syscall_instr))
84		return (0);
85
86	if (memcmp(instr, int_syscall_instr, sizeof (int_syscall_instr)) == 0)
87		return (1);
88
89	return (0);
90}
91
92int
93Pissyscall_prev(struct ps_prochandle *P, uintptr_t addr, uintptr_t *dst)
94{
95	int ret;
96
97	if (ret = Pissyscall(P, addr - sizeof (int_syscall_instr))) {
98		if (dst)
99			*dst = addr - sizeof (int_syscall_instr);
100		return (ret);
101	}
102
103	return (0);
104}
105
106/* ARGSUSED */
107int
108Pissyscall_text(struct ps_prochandle *P, const void *buf, size_t buflen)
109{
110	if (buflen < sizeof (int_syscall_instr))
111		return (0);
112
113	if (memcmp(buf, int_syscall_instr, sizeof (int_syscall_instr)) == 0)
114		return (1);
115
116	return (0);
117}
118
119#define	TR_ARG_MAX 6	/* Max args to print, same as SPARC */
120
121/*
122 * Given a return address, determine the likely number of arguments
123 * that were pushed on the stack prior to its execution.  We do this by
124 * expecting that a typical call sequence consists of pushing arguments on
125 * the stack, executing a call instruction, and then performing an add
126 * on %esp to restore it to the value prior to pushing the arguments for
127 * the call.  We attempt to detect such an add, and divide the addend
128 * by the size of a word to determine the number of pushed arguments.
129 *
130 * If we do not find such an add, this does not necessarily imply that the
131 * function took no arguments. It is not possible to reliably detect such a
132 * void function because hand-coded assembler does not always perform an add
133 * to %esp immediately after the "call" instruction (eg. _sys_call()).
134 * Because of this, we default to returning MIN(sz, TR_ARG_MAX) instead of 0
135 * in the absence of an add to %esp.
136 */
137static ulong_t
138argcount(struct ps_prochandle *P, long pc, ssize_t sz)
139{
140	uchar_t instr[6];
141	ulong_t count, max;
142
143	max = MIN(sz / sizeof (long), TR_ARG_MAX);
144
145	/*
146	 * Read the instruction at the return location.
147	 */
148	if (Pread(P, instr, sizeof (instr), pc) != sizeof (instr) ||
149	    instr[1] != 0xc4)
150		return (max);
151
152	switch (instr[0]) {
153	case 0x81:	/* count is a longword */
154		count = instr[2]+(instr[3]<<8)+(instr[4]<<16)+(instr[5]<<24);
155		break;
156	case 0x83:	/* count is a byte */
157		count = instr[2];
158		break;
159	default:
160		return (max);
161	}
162
163	count /= sizeof (long);
164	return (MIN(count, max));
165}
166
167static void
168ucontext_n_to_prgregs(const ucontext_t *src, prgregset_t dst)
169{
170	(void) memcpy(dst, src->uc_mcontext.gregs, sizeof (gregset_t));
171}
172
173int
174Pstack_iter(struct ps_prochandle *P, const prgregset_t regs,
175	proc_stack_f *func, void *arg)
176{
177	prgreg_t *prevfp = NULL;
178	uint_t pfpsize = 0;
179	int nfp = 0;
180	struct {
181		long	fp;
182		long	pc;
183		long	args[32];
184	} frame;
185	uint_t argc;
186	ssize_t sz;
187	prgregset_t gregs;
188	prgreg_t fp, pfp;
189	prgreg_t pc;
190	int rv;
191
192	/*
193	 * Type definition for a structure corresponding to an IA32
194	 * signal frame.  Refer to the comments in Pstack.c for more info
195	 */
196	typedef struct {
197		long fp;
198		long pc;
199		int signo;
200		ucontext_t *ucp;
201		siginfo_t *sip;
202	} sf_t;
203
204	uclist_t ucl;
205	ucontext_t uc;
206	uintptr_t uc_addr;
207
208	init_uclist(&ucl, P);
209	(void) memcpy(gregs, regs, sizeof (gregs));
210
211	fp = regs[R_FP];
212	pc = regs[R_PC];
213
214	while (fp != 0 || pc != 0) {
215		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))
216			break;
217
218		if (fp != 0 &&
219		    (sz = Pread(P, &frame, sizeof (frame), (uintptr_t)fp)
220		    >= (ssize_t)(2* sizeof (long)))) {
221			/*
222			 * One more trick for signal frames: the kernel sets
223			 * the return pc of the signal frame to 0xffffffff on
224			 * Intel IA32, so argcount won't work.
225			 */
226			if (frame.pc != -1L) {
227				sz -= 2* sizeof (long);
228				argc = argcount(P, (long)frame.pc, sz);
229			} else
230				argc = 3; /* sighandler(signo, sip, ucp) */
231		} else {
232			(void) memset(&frame, 0, sizeof (frame));
233			argc = 0;
234		}
235
236		gregs[R_FP] = fp;
237		gregs[R_PC] = pc;
238
239		if ((rv = func(arg, gregs, argc, frame.args)) != 0)
240			break;
241
242		/*
243		 * In order to allow iteration over java frames (which can have
244		 * their own frame pointers), we allow the iterator to change
245		 * the contents of gregs.  If we detect a change, then we assume
246		 * that the new values point to the next frame.
247		 */
248		if (gregs[R_FP] != fp || gregs[R_PC] != pc) {
249			fp = gregs[R_FP];
250			pc = gregs[R_PC];
251			continue;
252		}
253
254		pfp = fp;
255		fp = frame.fp;
256		pc = frame.pc;
257
258		if (find_uclink(&ucl, pfp + sizeof (sf_t)))
259			uc_addr = pfp + sizeof (sf_t);
260		else
261			uc_addr = NULL;
262
263		if (uc_addr != NULL &&
264		    Pread(P, &uc, sizeof (uc), uc_addr) == sizeof (uc)) {
265
266			ucontext_n_to_prgregs(&uc, gregs);
267			fp = gregs[R_FP];
268			pc = gregs[R_PC];
269		}
270	}
271
272	if (prevfp)
273		free(prevfp);
274
275	free_uclist(&ucl);
276	return (rv);
277}
278
279uintptr_t
280Psyscall_setup(struct ps_prochandle *P, int nargs, int sysindex, uintptr_t sp)
281{
282	sp -= sizeof (int) * (nargs+2);	/* space for arg list + CALL parms */
283
284	P->status.pr_lwp.pr_reg[EAX] = sysindex;
285	P->status.pr_lwp.pr_reg[R_SP] = sp;
286	P->status.pr_lwp.pr_reg[R_PC] = P->sysaddr;
287
288	return (sp);
289}
290
291int
292Psyscall_copyinargs(struct ps_prochandle *P, int nargs, argdes_t *argp,
293    uintptr_t ap)
294{
295	int32_t arglist[MAXARGS+2];
296	int i;
297	argdes_t *adp;
298
299	for (i = 0, adp = argp; i < nargs; i++, adp++)
300		arglist[1 + i] = (int32_t)adp->arg_value;
301
302	arglist[0] = P->status.pr_lwp.pr_reg[R_PC];
303	if (Pwrite(P, &arglist[0], sizeof (int) * (nargs+1),
304	    (uintptr_t)ap) != sizeof (int) * (nargs+1))
305		return (-1);
306
307	return (0);
308}
309
310int
311Psyscall_copyoutargs(struct ps_prochandle *P, int nargs, argdes_t *argp,
312    uintptr_t ap)
313{
314	uint32_t arglist[MAXARGS + 2];
315	int i;
316	argdes_t *adp;
317
318	if (Pread(P, &arglist[0], sizeof (int) * (nargs+1), (uintptr_t)ap)
319	    != sizeof (int) * (nargs+1))
320		return (-1);
321
322	for (i = 0, adp = argp; i < nargs; i++, adp++)
323		adp->arg_value = arglist[i];
324
325	return (0);
326}
327