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