xref: /illumos-gate/usr/src/lib/libproc/amd64/Pisadep.c (revision b1e2e3fb17324e9ddf43db264a0c64da7756d9e6)
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 
44 static uchar_t int_syscall_instr[] = { 0xCD, T_SYSCALLINT };
45 static uchar_t syscall_instr[] = { 0x0f, 0x05 };
46 
47 const char *
48 Ppltdest(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 
93 int
94 Pissyscall(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 
117 int
118 Pissyscall_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 
140 int
141 Pissyscall_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 
162 static boolean_t
163 argcount_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  */
200 static ulong_t
201 argcount(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 
232 static void
233 ucontext_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 
258 static int
259 Pstack_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 = NULL;
357 
358 		if (uc_addr != 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 
373 static void
374 ucontext_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  */
383 static int
384 read_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 
495 int
496 Pstack_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 
594 uintptr_t
595 Psyscall_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 
616 int
617 Psyscall_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 
675 int
676 Psyscall_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