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 * Copyright 2018, Joyent, Inc.
25 */
26
27#include <sys/stack.h>
28#include <sys/regset.h>
29#include <sys/frame.h>
30#include <sys/sysmacros.h>
31#include <sys/trap.h>
32#include <sys/machelf.h>
33
34#include <stdlib.h>
35#include <unistd.h>
36#include <sys/types.h>
37#include <errno.h>
38#include <string.h>
39
40#include <saveargs.h>
41#include "Pcontrol.h"
42#include "Pstack.h"
43
44static uchar_t int_syscall_instr[] = { 0xCD, T_SYSCALLINT };
45static uchar_t syscall_instr[] = { 0x0f, 0x05 };
46
47const char *
48Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
49{
50	map_info_t *mp = Paddr2mptr(P, pltaddr);
51	file_info_t *fp;
52	size_t i;
53	uintptr_t r_addr;
54
55	if (mp == NULL || (fp = mp->map_file) == NULL ||
56	    fp->file_plt_base == 0 ||
57	    pltaddr - fp->file_plt_base >= fp->file_plt_size) {
58		errno = EINVAL;
59		return (NULL);
60	}
61
62	i = (pltaddr - fp->file_plt_base) / M_PLT_ENTSIZE - M_PLT_XNumber;
63
64	if (P->status.pr_dmodel == PR_MODEL_LP64) {
65		Elf64_Rela r;
66
67		r_addr = fp->file_jmp_rel + i * sizeof (r);
68
69		if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
70		    (i = ELF64_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
71			Elf_Data *data = fp->file_dynsym.sym_data_pri;
72			Elf64_Sym *symp = &(((Elf64_Sym *)data->d_buf)[i]);
73
74			return (fp->file_dynsym.sym_strs + symp->st_name);
75		}
76	} else {
77		Elf32_Rel r;
78
79		r_addr = fp->file_jmp_rel + i * sizeof (r);
80
81		if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
82		    (i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
83			Elf_Data *data = fp->file_dynsym.sym_data_pri;
84			Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);
85
86			return (fp->file_dynsym.sym_strs + symp->st_name);
87		}
88	}
89
90	return (NULL);
91}
92
93int
94Pissyscall(struct ps_prochandle *P, uintptr_t addr)
95{
96	uchar_t instr[16];
97
98	if (P->status.pr_dmodel == PR_MODEL_LP64) {
99		if (Pread(P, instr, sizeof (syscall_instr), addr) !=
100		    sizeof (syscall_instr) ||
101		    memcmp(instr, syscall_instr, sizeof (syscall_instr)) != 0)
102			return (0);
103		else
104			return (1);
105	}
106
107	if (Pread(P, instr, sizeof (int_syscall_instr), addr) !=
108	    sizeof (int_syscall_instr))
109		return (0);
110
111	if (memcmp(instr, int_syscall_instr, sizeof (int_syscall_instr)) == 0)
112		return (1);
113
114	return (0);
115}
116
117int
118Pissyscall_prev(struct ps_prochandle *P, uintptr_t addr, uintptr_t *dst)
119{
120	int ret;
121
122	if (P->status.pr_dmodel == PR_MODEL_LP64) {
123		if (Pissyscall(P, addr - sizeof (syscall_instr))) {
124			if (dst)
125				*dst = addr - sizeof (syscall_instr);
126			return (1);
127		}
128		return (0);
129	}
130
131	if ((ret = Pissyscall(P, addr - sizeof (int_syscall_instr))) != 0) {
132		if (dst)
133			*dst = addr - sizeof (int_syscall_instr);
134		return (ret);
135	}
136
137	return (0);
138}
139
140int
141Pissyscall_text(struct ps_prochandle *P, const void *buf, size_t buflen)
142{
143	if (P->status.pr_dmodel == PR_MODEL_LP64) {
144		if (buflen >= sizeof (syscall_instr) &&
145		    memcmp(buf, syscall_instr, sizeof (syscall_instr)) == 0)
146			return (1);
147		else
148			return (0);
149	}
150
151	if (buflen < sizeof (int_syscall_instr))
152		return (0);
153
154	if (memcmp(buf, int_syscall_instr, sizeof (int_syscall_instr)) == 0)
155		return (1);
156
157	return (0);
158}
159
160#define	TR_ARG_MAX 6	/* Max args to print, same as SPARC */
161
162static boolean_t
163argcount_ctf(struct ps_prochandle *P, uint32_t pc, uint_t *countp)
164{
165	GElf_Sym sym;
166	ctf_file_t *ctfp;
167	ctf_funcinfo_t finfo;
168	prsyminfo_t si = { 0 };
169
170	if (Pxlookup_by_addr(P, pc, NULL, 0, &sym, &si) != 0)
171		return (B_FALSE);
172
173	if ((ctfp = Paddr_to_ctf(P, pc)) == NULL)
174		return (B_FALSE);
175
176	if (ctf_func_info(ctfp, si.prs_id, &finfo) == CTF_ERR)
177		return (B_FALSE);
178
179	*countp = finfo.ctc_argc;
180
181	return (B_TRUE);
182}
183
184/*
185 * Given a return address, determine the likely number of arguments
186 * that were pushed on the stack prior to its execution.  We do this by
187 * expecting that a typical call sequence consists of pushing arguments on
188 * the stack, executing a call instruction, and then performing an add
189 * on %esp to restore it to the value prior to pushing the arguments for
190 * the call.  We attempt to detect such an add, and divide the addend
191 * by the size of a word to determine the number of pushed arguments.
192 *
193 * If we do not find such an add, this does not necessarily imply that the
194 * function took no arguments. It is not possible to reliably detect such a
195 * void function because hand-coded assembler does not always perform an add
196 * to %esp immediately after the "call" instruction (eg. _sys_call()).
197 * Because of this, we default to returning MIN(sz, TR_ARG_MAX) instead of 0
198 * in the absence of an add to %esp.
199 */
200static ulong_t
201argcount(struct ps_prochandle *P, uint32_t pc, ssize_t sz)
202{
203	uchar_t instr[6];
204	ulong_t count, max;
205
206	max = MIN(sz / sizeof (uint32_t), TR_ARG_MAX);
207
208	/*
209	 * Read the instruction at the return location.
210	 */
211	if (Pread(P, instr, sizeof (instr), (uintptr_t)pc) != sizeof (instr))
212		return (max);
213
214	if (instr[1] != 0xc4)
215		return (max);
216
217	switch (instr[0]) {
218	case 0x81:	/* count is a longword */
219		count = instr[2]+(instr[3]<<8)+(instr[4]<<16)+(instr[5]<<24);
220		break;
221	case 0x83:	/* count is a byte */
222		count = instr[2];
223		break;
224	default:
225		return (max);
226	}
227
228	count /= sizeof (uint32_t);
229	return (MIN(count, max));
230}
231
232static void
233ucontext_32_to_prgregs(const ucontext32_t *uc, prgregset_t dst)
234{
235	const greg32_t *src = &uc->uc_mcontext.gregs[0];
236
237	dst[REG_DS] = (uint16_t)src[DS];
238	dst[REG_ES] = (uint16_t)src[ES];
239
240	dst[REG_GS] = (uint16_t)src[GS];
241	dst[REG_FS] = (uint16_t)src[FS];
242	dst[REG_SS] = (uint16_t)src[SS];
243	dst[REG_RSP] = (uint32_t)src[UESP];
244	dst[REG_RFL] = src[EFL];
245	dst[REG_CS] = (uint16_t)src[CS];
246	dst[REG_RIP] = (uint32_t)src[EIP];
247	dst[REG_ERR] = (uint32_t)src[ERR];
248	dst[REG_TRAPNO] = (uint32_t)src[TRAPNO];
249	dst[REG_RAX] = (uint32_t)src[EAX];
250	dst[REG_RCX] = (uint32_t)src[ECX];
251	dst[REG_RDX] = (uint32_t)src[EDX];
252	dst[REG_RBX] = (uint32_t)src[EBX];
253	dst[REG_RBP] = (uint32_t)src[EBP];
254	dst[REG_RSI] = (uint32_t)src[ESI];
255	dst[REG_RDI] = (uint32_t)src[EDI];
256}
257
258static int
259Pstack_iter32(struct ps_prochandle *P, const prgregset_t regs,
260    proc_stack_f *func, void *arg)
261{
262	prgreg_t *prevfp = NULL;
263	uint_t pfpsize = 0;
264	int nfp = 0;
265	struct {
266		prgreg32_t fp;
267		prgreg32_t pc;
268		prgreg32_t args[32];
269	} frame;
270	uint_t argc;
271	ssize_t sz;
272	prgregset_t gregs;
273	uint32_t fp, pfp, pc, ctf_pc;
274	long args[32];
275	int rv;
276	int i;
277
278	/*
279	 * Type definition for a structure corresponding to an IA32
280	 * signal frame.  Refer to the comments in Pstack.c for more info
281	 */
282	typedef struct {
283		prgreg32_t fp;
284		prgreg32_t pc;
285		int signo;
286		caddr32_t ucp;
287		caddr32_t sip;
288	} sf_t;
289
290	uclist_t ucl;
291	ucontext32_t uc;
292	uintptr_t uc_addr;
293
294	init_uclist(&ucl, P);
295	(void) memcpy(gregs, regs, sizeof (gregs));
296
297	fp = regs[R_FP];
298	ctf_pc = pc = regs[R_PC];
299
300	while (fp != 0 || pc != 0) {
301		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))
302			break;
303
304		if (fp != 0 &&
305		    (sz = Pread(P, &frame, sizeof (frame), (uintptr_t)fp)
306		    >= (ssize_t)(2* sizeof (uint32_t)))) {
307			/*
308			 * One more trick for signal frames: the kernel sets
309			 * the return pc of the signal frame to 0xffffffff on
310			 * Intel IA32, so argcount won't work.
311			 */
312			if (frame.pc != -1L) {
313				sz -= 2* sizeof (uint32_t);
314				if (argcount_ctf(P, ctf_pc, &argc)) {
315					argc = MIN(argc, 32);
316				} else {
317					argc = argcount(P, (uint32_t)frame.pc,
318					    sz);
319				}
320			} else
321				argc = 3; /* sighandler(signo, sip, ucp) */
322		} else {
323			(void) memset(&frame, 0, sizeof (frame));
324			argc = 0;
325		}
326
327		ctf_pc = frame.pc;
328		gregs[R_FP] = fp;
329		gregs[R_PC] = pc;
330
331		for (i = 0; i < argc; i++)
332			args[i] = (uint32_t)frame.args[i];
333
334		if ((rv = func(arg, gregs, argc, args)) != 0)
335			break;
336
337		/*
338		 * In order to allow iteration over java frames (which can have
339		 * their own frame pointers), we allow the iterator to change
340		 * the contents of gregs.  If we detect a change, then we assume
341		 * that the new values point to the next frame.
342		 */
343		if (gregs[R_FP] != fp || gregs[R_PC] != pc) {
344			fp = gregs[R_FP];
345			pc = gregs[R_PC];
346			continue;
347		}
348
349		pfp = fp;
350		fp = frame.fp;
351		pc = frame.pc;
352
353		if (find_uclink(&ucl, pfp + sizeof (sf_t)))
354			uc_addr = pfp + sizeof (sf_t);
355		else
356			uc_addr = (uintptr_t)NULL;
357
358		if (uc_addr != (uintptr_t)NULL &&
359		    Pread(P, &uc, sizeof (uc), uc_addr) == sizeof (uc)) {
360			ucontext_32_to_prgregs(&uc, gregs);
361			fp = gregs[R_FP];
362			pc = gregs[R_PC];
363		}
364	}
365
366	if (prevfp)
367		free(prevfp);
368
369	free_uclist(&ucl);
370	return (rv);
371}
372
373static void
374ucontext_n_to_prgregs(const ucontext_t *src, prgregset_t dst)
375{
376	(void) memcpy(dst, src->uc_mcontext.gregs, sizeof (gregset_t));
377}
378
379/*
380 * Read arguments from the frame indicated by regs into args, return the
381 * number of arguments successfully read
382 */
383static int
384read_args(struct ps_prochandle *P, uintptr_t fp, uintptr_t pc, prgreg_t *args,
385    size_t argsize)
386{
387	GElf_Sym sym;
388	ctf_file_t *ctfp = NULL;
389	ctf_funcinfo_t finfo;
390	prsyminfo_t si = {0};
391	uint8_t ins[SAVEARGS_INSN_SEQ_LEN];
392	size_t insnsize;
393	int argc = 0;
394	int rettype = 0;
395	int start_index = 0;
396	int args_style = 0;
397	int i;
398	ctf_id_t args_types[5];
399
400	if (Pxlookup_by_addr(P, pc, NULL, 0, &sym, &si) != 0)
401		return (0);
402
403	if ((ctfp = Paddr_to_ctf(P, pc)) == NULL)
404		return (0);
405
406	if (ctf_func_info(ctfp, si.prs_id, &finfo) == CTF_ERR)
407		return (0);
408
409	argc = finfo.ctc_argc;
410
411	if (argc == 0)
412		return (0);
413
414	rettype = ctf_type_kind(ctfp, finfo.ctc_return);
415
416	/*
417	 * If the function returns a structure or union greater than 16 bytes
418	 * in size %rdi contains the address in which to store the return
419	 * value rather than for an argument.
420	 */
421	if (((rettype == CTF_K_STRUCT) || (rettype == CTF_K_UNION)) &&
422	    ctf_type_size(ctfp, finfo.ctc_return) > 16)
423		start_index = 1;
424	else
425		start_index = 0;
426
427	/*
428	 * If any of the first 5 arguments are a structure less than 16 bytes
429	 * in size, it will be passed spread across two argument registers,
430	 * and we will not cope.
431	 */
432	if (ctf_func_args(ctfp, si.prs_id, 5, args_types) == CTF_ERR)
433		return (0);
434
435	for (i = 0; i < MIN(5, finfo.ctc_argc); i++) {
436		int t = ctf_type_kind(ctfp, args_types[i]);
437
438		if (((t == CTF_K_STRUCT) || (t == CTF_K_UNION)) &&
439		    ctf_type_size(ctfp, args_types[i]) <= 16)
440			return (0);
441	}
442
443	/*
444	 * The number of instructions to search for argument saving is limited
445	 * such that only instructions prior to %pc are considered and we
446	 * never read arguments from a function where the saving code has not
447	 * in fact yet executed.
448	 */
449	insnsize = MIN(MIN(sym.st_size, SAVEARGS_INSN_SEQ_LEN),
450	    pc - sym.st_value);
451
452	if (Pread(P, ins, insnsize, sym.st_value) != insnsize)
453		return (0);
454
455	if ((argc != 0) &&
456	    ((args_style = saveargs_has_args(ins, insnsize, argc,
457	    start_index)) != SAVEARGS_NO_ARGS)) {
458		int regargs = MIN((6 - start_index), argc);
459		size_t size = regargs * sizeof (long);
460		int i;
461
462		/*
463		 * If Studio pushed a structure return address as an argument,
464		 * we need to read one more argument than actually exists (the
465		 * addr) to make everything line up.
466		 */
467		if (args_style == SAVEARGS_STRUCT_ARGS)
468			size += sizeof (long);
469
470		if (Pread(P, args, size, (fp - size)) != size)
471			return (0);
472
473		for (i = 0; i < (regargs / 2); i++) {
474			prgreg_t t = args[i];
475
476			args[i] = args[regargs - i - 1];
477			args[regargs - i - 1] = t;
478		}
479
480		if (argc > regargs) {
481			size = MIN((argc - regargs) * sizeof (long),
482			    argsize - (regargs * sizeof (long)));
483
484			if (Pread(P, &args[regargs], size, fp +
485			    (sizeof (uintptr_t) * 2)) != size)
486				return (6);
487		}
488
489		return (argc);
490	} else {
491		return (0);
492	}
493}
494
495int
496Pstack_iter(struct ps_prochandle *P, const prgregset_t regs,
497    proc_stack_f *func, void *arg)
498{
499	struct {
500		uintptr_t fp;
501		uintptr_t pc;
502	} frame;
503
504	uint_t pfpsize = 0;
505	prgreg_t *prevfp = NULL;
506	prgreg_t fp, pfp;
507	prgreg_t pc;
508
509	prgregset_t gregs;
510	int nfp = 0;
511
512	uclist_t ucl;
513	int rv = 0;
514	int argc;
515
516	uintptr_t uc_addr;
517	ucontext_t uc;
518
519	/*
520	 * Type definition for a structure corresponding to an IA32
521	 * signal frame.  Refer to the comments in Pstack.c for more info
522	 */
523	typedef struct {
524		prgreg_t fp;
525		prgreg_t pc;
526		prgreg_t signo;
527		siginfo_t *sip;
528	} sigframe_t;
529	prgreg_t args[32] = {0};
530
531	if (P->status.pr_dmodel != PR_MODEL_LP64)
532		return (Pstack_iter32(P, regs, func, arg));
533
534	init_uclist(&ucl, P);
535	(void) memcpy(gregs, regs, sizeof (gregs));
536
537	fp = gregs[R_FP];
538	pc = gregs[R_PC];
539
540	while (fp != 0 || pc != 0) {
541
542		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))
543			break;
544
545		if (fp != 0 &&
546		    Pread(P, &frame, sizeof (frame), (uintptr_t)fp) ==
547		    sizeof (frame)) {
548			if (frame.pc == -1) {
549				argc = 3;
550				args[2] = fp + sizeof (sigframe_t);
551				if (Pread(P, &args, 2 * sizeof (prgreg_t),
552				    fp + 2 * sizeof (prgreg_t)) !=
553				    2 * sizeof (prgreg_t))
554					argc = 0;
555			} else {
556				argc = read_args(P, fp, pc, args,
557				    sizeof (args));
558			}
559		} else {
560			(void) memset(&frame, 0, sizeof (frame));
561			argc = 0;
562		}
563
564		gregs[R_FP] = fp;
565		gregs[R_PC] = pc;
566
567		if ((rv = func(arg, gregs, argc, args)) != 0)
568			break;
569
570		pfp = fp;
571		fp = frame.fp;
572		pc = frame.pc;
573
574		if (pc == -1 && find_uclink(&ucl, pfp + sizeof (sigframe_t))) {
575			uc_addr = pfp + sizeof (sigframe_t);
576
577			if (Pread(P, &uc, sizeof (uc), uc_addr)
578			    == sizeof (uc)) {
579				ucontext_n_to_prgregs(&uc, gregs);
580				fp = gregs[R_FP];
581				pc = gregs[R_PC];
582			}
583		}
584	}
585
586	if (prevfp)
587		free(prevfp);
588
589	free_uclist(&ucl);
590
591	return (rv);
592}
593
594uintptr_t
595Psyscall_setup(struct ps_prochandle *P, int nargs, int sysindex, uintptr_t sp)
596{
597	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
598		sp -= sizeof (int) * (nargs+2);
599
600		P->status.pr_lwp.pr_reg[REG_RAX] = sysindex;
601		P->status.pr_lwp.pr_reg[REG_RSP] = sp;
602		P->status.pr_lwp.pr_reg[REG_RIP] = P->sysaddr;
603	} else {
604		int pusharg = (nargs > 6) ? nargs - 6: 0;
605
606		sp -= sizeof (int64_t) * (pusharg+2);
607
608		P->status.pr_lwp.pr_reg[REG_RAX] = sysindex;
609		P->status.pr_lwp.pr_reg[REG_RSP] = sp;
610		P->status.pr_lwp.pr_reg[REG_RIP] = P->sysaddr;
611	}
612
613	return (sp);
614}
615
616int
617Psyscall_copyinargs(struct ps_prochandle *P, int nargs, argdes_t *argp,
618    uintptr_t ap)
619{
620	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
621		int32_t arglist[MAXARGS+2];
622		int i;
623		argdes_t *adp;
624
625		for (i = 0, adp = argp; i < nargs; i++, adp++)
626			arglist[1 + i] = (int32_t)adp->arg_value;
627
628		arglist[0] = P->status.pr_lwp.pr_reg[REG_RIP];
629		if (Pwrite(P, &arglist[0], sizeof (int) * (nargs+1),
630		    (uintptr_t)ap) != sizeof (int) * (nargs+1))
631			return (-1);
632	} else {
633		int64_t arglist[MAXARGS+2];
634		int i;
635		argdes_t *adp;
636		int pusharg = (nargs > 6) ? nargs - 6: 0;
637
638		for (i = 0, adp = argp; i < nargs; i++, adp++) {
639			switch (i) {
640			case 0:
641				(void) Pputareg(P, REG_RDI, adp->arg_value);
642				break;
643			case 1:
644				(void) Pputareg(P, REG_RSI, adp->arg_value);
645				break;
646			case 2:
647				(void) Pputareg(P, REG_RDX, adp->arg_value);
648				break;
649			case 3:
650				(void) Pputareg(P, REG_RCX, adp->arg_value);
651				break;
652			case 4:
653				(void) Pputareg(P, REG_R8, adp->arg_value);
654				break;
655			case 5:
656				(void) Pputareg(P, REG_R9, adp->arg_value);
657				break;
658			default:
659				arglist[i - 5] = (uint64_t)adp->arg_value;
660				break;
661			}
662		}
663
664		arglist[0] = P->status.pr_lwp.pr_reg[REG_RIP];
665
666		if (Pwrite(P, &arglist[0],
667		    sizeof (int64_t) * (pusharg + 1), ap) !=
668		    sizeof (int64_t) * (pusharg + 1))
669			return (-1);
670	}
671
672	return (0);
673}
674
675int
676Psyscall_copyoutargs(struct ps_prochandle *P, int nargs, argdes_t *argp,
677    uintptr_t ap)
678{
679	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
680		uint32_t arglist[MAXARGS + 2];
681		int i;
682		argdes_t *adp;
683
684		if (Pread(P, &arglist[0], sizeof (int) * (nargs+1),
685		    (uintptr_t)ap) != sizeof (int) * (nargs+1))
686			return (-1);
687
688		for (i = 0, adp = argp; i < nargs; i++, adp++)
689			adp->arg_value = arglist[i];
690	} else {
691		int pusharg = (nargs > 6) ? nargs - 6: 0;
692		int64_t arglist[MAXARGS+2];
693		int i;
694		argdes_t *adp;
695
696		if (pusharg  > 0 &&
697		    Pread(P, &arglist[0], sizeof (int64_t) * (pusharg + 1),
698		    ap) != sizeof (int64_t) * (pusharg + 1))
699			return (-1);
700
701		for (i = 0, adp = argp; i < nargs; i++, adp++) {
702			switch (i) {
703			case 0:
704				adp->arg_value =
705				    P->status.pr_lwp.pr_reg[REG_RDI];
706				break;
707			case 1:
708				adp->arg_value =
709				    P->status.pr_lwp.pr_reg[REG_RSI];
710				break;
711			case 2:
712				adp->arg_value =
713				    P->status.pr_lwp.pr_reg[REG_RDX];
714				break;
715			case 3:
716				adp->arg_value =
717				    P->status.pr_lwp.pr_reg[REG_RCX];
718				break;
719			case 4:
720				adp->arg_value =
721				    P->status.pr_lwp.pr_reg[REG_R8];
722				break;
723			case 5:
724				adp->arg_value =
725				    P->status.pr_lwp.pr_reg[REG_R9];
726				break;
727			default:
728				adp->arg_value = arglist[i - 6];
729				break;
730			}
731		}
732
733		return (0);
734	}
735
736	return (0);
737}
738