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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #define __sparcv9cpu 29 30 #include <sys/stack.h> 31 #include <sys/regset.h> 32 #include <sys/frame.h> 33 #include <sys/sysmacros.h> 34 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <sys/types.h> 38 #include <errno.h> 39 #include <string.h> 40 41 #include "Pcontrol.h" 42 #include "Pstack.h" 43 #include "Pisadep.h" 44 #include "P32ton.h" 45 46 #define M_PLT32_NRSV 4 /* reserved PLT entries */ 47 #define M_PLT32_ENTSIZE 12 /* size of each PLT entry */ 48 49 #define M_PLT64_NRSV 4 /* reserved bit PLT entries */ 50 #define M_PLT64_ENTSIZE 32 /* size of each PLT entry */ 51 #define M_PLT64_FENTSIZE 24 /* size of far PLT entry */ 52 #define M_PLT64_NEARPLTS 0x8000 /* # of NEAR PLTS we can have */ 53 #define M_PLT64_FBLKCNTS 160 /* # of plts in far PLT blocks */ 54 #define M_PLT64_FBLOCKSZ (M_PLT64_FBLKCNTS * \ 55 (M_PLT64_FENTSIZE + sizeof (uint64_t))) 56 /* size of far PLT block */ 57 58 #define SYSCALL32 0x91d02008 /* 32-bit syscall (ta 8) instruction */ 59 #define SYSCALL64 0x91d02040 /* 64-bit syscall (ta 64) instruction */ 60 61 const char * 62 Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr) 63 { 64 map_info_t *mp = Paddr2mptr(P, pltaddr); 65 66 uintptr_t r_addr; 67 file_info_t *fp; 68 size_t i; 69 70 if (mp == NULL || (fp = mp->map_file) == NULL || 71 fp->file_plt_base == 0 || pltaddr < fp->file_plt_base || 72 pltaddr >= fp->file_plt_base + fp->file_plt_size) { 73 errno = EINVAL; 74 return (NULL); 75 } 76 77 if (P->status.pr_dmodel == PR_MODEL_LP64) { 78 Elf64_Rela r; 79 uintptr_t pltoff; 80 81 pltoff = pltaddr - fp->file_plt_base; 82 if (pltoff < (M_PLT64_NEARPLTS * M_PLT64_ENTSIZE)) { 83 i = (pltaddr - fp->file_plt_base - 84 M_PLT64_NRSV * M_PLT64_ENTSIZE) / M_PLT64_ENTSIZE; 85 } else { 86 uintptr_t pltblockoff; 87 pltblockoff = pltoff - (M_PLT64_NEARPLTS * 88 M_PLT64_ENTSIZE); 89 i = M_PLT64_NEARPLTS + 90 ((pltblockoff / M_PLT64_FBLOCKSZ) * 91 M_PLT64_FBLKCNTS) + ((pltblockoff % 92 M_PLT64_FBLOCKSZ) / M_PLT64_FENTSIZE) - 93 M_PLT64_NRSV; 94 } 95 96 r_addr = fp->file_jmp_rel + i * sizeof (Elf64_Rela); 97 98 if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) && 99 (i = ELF64_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) { 100 101 Elf_Data *data = fp->file_dynsym.sym_data_pri; 102 Elf64_Sym *symp = &(((Elf64_Sym *)data->d_buf)[i]); 103 104 return (fp->file_dynsym.sym_strs + symp->st_name); 105 } 106 107 } else /* PR_MODEL_ILP32 */ { 108 Elf32_Rela r; 109 110 i = (pltaddr - fp->file_plt_base - 111 M_PLT32_NRSV * M_PLT32_ENTSIZE) / M_PLT32_ENTSIZE; 112 113 r_addr = fp->file_jmp_rel + i * sizeof (Elf32_Rela); 114 115 if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) && 116 (i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) { 117 118 Elf_Data *data = fp->file_dynsym.sym_data_pri; 119 Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]); 120 121 return (fp->file_dynsym.sym_strs + symp->st_name); 122 } 123 } 124 125 return (NULL); 126 } 127 128 int 129 Pissyscall(struct ps_prochandle *P, uintptr_t addr) 130 { 131 instr_t sysinstr; 132 instr_t instr; 133 134 if (P->status.pr_dmodel == PR_MODEL_LP64) 135 sysinstr = SYSCALL64; 136 else 137 sysinstr = SYSCALL32; 138 139 if (Pread(P, &instr, sizeof (instr), addr) != sizeof (instr) || 140 instr != sysinstr) 141 return (0); 142 else 143 return (1); 144 } 145 146 int 147 Pissyscall_prev(struct ps_prochandle *P, uintptr_t addr, uintptr_t *dst) 148 { 149 uintptr_t prevaddr = addr - sizeof (instr_t); 150 151 if (Pissyscall(P, prevaddr)) { 152 if (dst) 153 *dst = prevaddr; 154 return (1); 155 } 156 157 return (0); 158 } 159 160 /* ARGSUSED */ 161 int 162 Pissyscall_text(struct ps_prochandle *P, const void *buf, size_t buflen) 163 { 164 instr_t sysinstr; 165 166 if (P->status.pr_dmodel == PR_MODEL_LP64) 167 sysinstr = SYSCALL64; 168 else 169 sysinstr = SYSCALL32; 170 171 if (buflen >= sizeof (instr_t) && 172 memcmp(buf, &sysinstr, sizeof (instr_t)) == 0) 173 return (1); 174 else 175 return (0); 176 } 177 178 /* 179 * For gwindows_t support, we define a structure to pass arguments to 180 * a Plwp_iter() callback routine. 181 */ 182 typedef struct { 183 struct ps_prochandle *gq_proc; /* libproc handle */ 184 struct rwindow *gq_rwin; /* rwindow destination buffer */ 185 uintptr_t gq_addr; /* stack address to match */ 186 } gwin_query_t; 187 188 static int 189 find_gwin(gwin_query_t *gqp, const lwpstatus_t *psp) 190 { 191 gwindows_t gwin; 192 struct stat64 st; 193 char path[64]; 194 ssize_t n; 195 int fd, i; 196 int rv = 0; /* Return value for skip to next lwp */ 197 198 (void) snprintf(path, sizeof (path), "/proc/%d/lwp/%d/gwindows", 199 (int)gqp->gq_proc->pid, (int)psp->pr_lwpid); 200 201 if (stat64(path, &st) == -1 || st.st_size == 0) 202 return (0); /* Nothing doing; skip to next lwp */ 203 204 if ((fd = open64(path, O_RDONLY)) >= 0) { 205 /* 206 * Zero out the gwindows_t because the gwindows file only has 207 * as much data as needed to represent the saved windows. 208 */ 209 if (gqp->gq_proc->status.pr_dmodel == PR_MODEL_ILP32) { 210 gwindows32_t g32; 211 212 (void) memset(&g32, 0, sizeof (g32)); 213 if ((n = read(fd, &g32, sizeof (g32))) > 0) 214 gwindows_32_to_n(&g32, &gwin); 215 216 } else { 217 (void) memset(&gwin, 0, sizeof (gwin)); 218 n = read(fd, &gwin, sizeof (gwin)); 219 } 220 221 if (n > 0) { 222 /* 223 * If we actually found a non-zero gwindows file and 224 * were able to read it, iterate through the buffers 225 * looking for a stack pointer match; if one is found, 226 * copy out the corresponding register window. 227 */ 228 for (i = 0; i < gwin.wbcnt; i++) { 229 if (gwin.spbuf[i] == (greg_t *)gqp->gq_addr) { 230 (void) memcpy(gqp->gq_rwin, 231 &gwin.wbuf[i], 232 sizeof (struct rwindow)); 233 234 rv = 1; /* We're done */ 235 break; 236 } 237 } 238 } 239 (void) close(fd); 240 } 241 242 return (rv); 243 } 244 245 static int 246 read_gwin(struct ps_prochandle *P, struct rwindow *rwp, uintptr_t sp) 247 { 248 gwin_query_t gq; 249 250 if (P->state == PS_DEAD) { 251 lwp_info_t *lwp = list_next(&P->core->core_lwp_head); 252 uint_t n; 253 int i; 254 255 for (n = 0; n < P->core->core_nlwp; n++, lwp = list_next(lwp)) { 256 gwindows_t *gwin = lwp->lwp_gwins; 257 258 if (gwin == NULL) 259 continue; /* No gwindows for this lwp */ 260 261 /* 262 * If this lwp has gwindows associated with it, iterate 263 * through the buffers looking for a stack pointer 264 * match; if one is found, copy out the register window. 265 */ 266 for (i = 0; i < gwin->wbcnt; i++) { 267 if (gwin->spbuf[i] == (greg_t *)sp) { 268 (void) memcpy(rwp, &gwin->wbuf[i], 269 sizeof (struct rwindow)); 270 return (0); /* We're done */ 271 } 272 } 273 } 274 275 return (-1); /* No gwindows match found */ 276 277 } 278 279 gq.gq_proc = P; 280 gq.gq_rwin = rwp; 281 gq.gq_addr = sp; 282 283 return (Plwp_iter(P, (proc_lwp_f *)find_gwin, &gq) ? 0 : -1); 284 } 285 286 static void 287 ucontext_n_to_prgregs(const ucontext_t *src, prgregset_t dst) 288 { 289 const greg_t *gregs = &src->uc_mcontext.gregs[0]; 290 291 dst[R_CCR] = gregs[REG_CCR]; 292 dst[R_ASI] = gregs[REG_ASI]; 293 dst[R_FPRS] = gregs[REG_FPRS]; 294 dst[R_PC] = gregs[REG_PC]; 295 dst[R_nPC] = gregs[REG_nPC]; 296 dst[R_Y] = gregs[REG_Y]; 297 298 dst[R_G1] = gregs[REG_G1]; 299 dst[R_G2] = gregs[REG_G2]; 300 dst[R_G3] = gregs[REG_G3]; 301 dst[R_G4] = gregs[REG_G4]; 302 dst[R_G5] = gregs[REG_G5]; 303 dst[R_G6] = gregs[REG_G6]; 304 dst[R_G7] = gregs[REG_G7]; 305 306 dst[R_O0] = gregs[REG_O0]; 307 dst[R_O1] = gregs[REG_O1]; 308 dst[R_O2] = gregs[REG_O2]; 309 dst[R_O3] = gregs[REG_O3]; 310 dst[R_O4] = gregs[REG_O4]; 311 dst[R_O5] = gregs[REG_O5]; 312 dst[R_O6] = gregs[REG_O6]; 313 dst[R_O7] = gregs[REG_O7]; 314 } 315 316 static void 317 ucontext_32_to_prgregs(const ucontext32_t *src, prgregset_t dst) 318 { 319 /* 320 * We need to be very careful here to cast the greg32_t's (signed) to 321 * unsigned and then explicitly promote them as unsigned values. 322 */ 323 const greg32_t *gregs = &src->uc_mcontext.gregs[0]; 324 325 dst[R_PSR] = (uint64_t)(uint32_t)gregs[REG_PSR]; 326 dst[R_PC] = (uint64_t)(uint32_t)gregs[REG_PC]; 327 dst[R_nPC] = (uint64_t)(uint32_t)gregs[REG_nPC]; 328 dst[R_Y] = (uint64_t)(uint32_t)gregs[REG_Y]; 329 330 dst[R_G1] = (uint64_t)(uint32_t)gregs[REG_G1]; 331 dst[R_G2] = (uint64_t)(uint32_t)gregs[REG_G2]; 332 dst[R_G3] = (uint64_t)(uint32_t)gregs[REG_G3]; 333 dst[R_G4] = (uint64_t)(uint32_t)gregs[REG_G4]; 334 dst[R_G5] = (uint64_t)(uint32_t)gregs[REG_G5]; 335 dst[R_G6] = (uint64_t)(uint32_t)gregs[REG_G6]; 336 dst[R_G7] = (uint64_t)(uint32_t)gregs[REG_G7]; 337 338 dst[R_O0] = (uint64_t)(uint32_t)gregs[REG_O0]; 339 dst[R_O1] = (uint64_t)(uint32_t)gregs[REG_O1]; 340 dst[R_O2] = (uint64_t)(uint32_t)gregs[REG_O2]; 341 dst[R_O3] = (uint64_t)(uint32_t)gregs[REG_O3]; 342 dst[R_O4] = (uint64_t)(uint32_t)gregs[REG_O4]; 343 dst[R_O5] = (uint64_t)(uint32_t)gregs[REG_O5]; 344 dst[R_O6] = (uint64_t)(uint32_t)gregs[REG_O6]; 345 dst[R_O7] = (uint64_t)(uint32_t)gregs[REG_O7]; 346 } 347 348 int 349 Pstack_iter(struct ps_prochandle *P, const prgregset_t regs, 350 proc_stack_f *func, void *arg) 351 { 352 prgreg_t *prevfp = NULL; 353 uint_t pfpsize = 0; 354 int nfp = 0; 355 prgregset_t gregs; 356 long args[6]; 357 prgreg_t fp; 358 int i; 359 int rv; 360 uintptr_t sp; 361 ssize_t n; 362 uclist_t ucl; 363 ucontext_t uc; 364 365 init_uclist(&ucl, P); 366 (void) memcpy(gregs, regs, sizeof (gregs)); 367 368 for (;;) { 369 fp = gregs[R_FP]; 370 if (stack_loop(fp, &prevfp, &nfp, &pfpsize)) 371 break; 372 373 for (i = 0; i < 6; i++) 374 args[i] = gregs[R_I0 + i]; 375 if ((rv = func(arg, gregs, 6, args)) != 0) 376 break; 377 378 gregs[R_PC] = gregs[R_I7]; 379 gregs[R_nPC] = gregs[R_PC] + 4; 380 (void) memcpy(&gregs[R_O0], &gregs[R_I0], 8*sizeof (prgreg_t)); 381 if ((sp = gregs[R_FP]) == 0) 382 break; 383 384 if (P->status.pr_dmodel == PR_MODEL_ILP32) { 385 struct rwindow32 rw32; 386 ucontext32_t uc32; 387 388 if (find_uclink(&ucl, sp + 389 SA32(sizeof (struct frame32))) && 390 Pread(P, &uc32, sizeof (uc32), sp + 391 SA32(sizeof (struct frame32))) == sizeof (uc32)) { 392 ucontext_32_to_prgregs(&uc32, gregs); 393 sp = gregs[R_SP]; 394 } 395 396 n = Pread(P, &rw32, sizeof (struct rwindow32), sp); 397 398 if (n == sizeof (struct rwindow32)) { 399 rwindow_32_to_n(&rw32, 400 (struct rwindow *)&gregs[R_L0]); 401 continue; 402 } 403 404 } else { 405 sp += STACK_BIAS; 406 407 if (find_uclink(&ucl, sp + SA(sizeof (struct frame))) && 408 Pread(P, &uc, sizeof (uc), sp + 409 SA(sizeof (struct frame))) == sizeof (uc)) { 410 ucontext_n_to_prgregs(&uc, gregs); 411 sp = gregs[R_SP] + STACK_BIAS; 412 } 413 414 n = Pread(P, &gregs[R_L0], sizeof (struct rwindow), sp); 415 416 if (n == sizeof (struct rwindow)) 417 continue; 418 } 419 420 /* 421 * If we get here, then our Pread of the register window 422 * failed. If this is because the address was not mapped, 423 * then we attempt to read this window via any gwindows 424 * information we have. If that too fails, abort our loop. 425 */ 426 if (n > 0) 427 break; /* Failed for reason other than not mapped */ 428 429 if (read_gwin(P, (struct rwindow *)&gregs[R_L0], sp) == -1) 430 break; /* No gwindows match either */ 431 } 432 433 if (prevfp) 434 free(prevfp); 435 436 free_uclist(&ucl); 437 return (rv); 438 } 439 440 uintptr_t 441 Psyscall_setup(struct ps_prochandle *P, int nargs, int sysindex, uintptr_t sp) 442 { 443 uintptr_t ret; 444 int model = P->status.pr_dmodel; 445 446 if (model == PR_MODEL_LP64) { 447 sp -= (nargs > 6)? 448 WINDOWSIZE64 + sizeof (int64_t) * nargs : 449 WINDOWSIZE64 + sizeof (int64_t) * 6; 450 sp = PSTACK_ALIGN64(sp); 451 ret = sp + WINDOWSIZE32 + sizeof (int32_t); 452 } else { 453 sp -= (nargs > 6)? 454 WINDOWSIZE32 + sizeof (int32_t) * (1 + nargs) : 455 WINDOWSIZE32 + sizeof (int32_t) * (1 + 6); 456 sp = PSTACK_ALIGN32(sp); 457 ret = sp + WINDOWSIZE64 + sizeof (int32_t); 458 } 459 460 P->status.pr_lwp.pr_reg[R_G1] = sysindex; 461 if (model == PR_MODEL_LP64) 462 P->status.pr_lwp.pr_reg[R_SP] = sp - STACK_BIAS; 463 else 464 P->status.pr_lwp.pr_reg[R_SP] = sp; 465 P->status.pr_lwp.pr_reg[R_PC] = P->sysaddr; 466 P->status.pr_lwp.pr_reg[R_nPC] = P->sysaddr + sizeof (instr_t); 467 468 return (ret); 469 } 470 471 int 472 Psyscall_copyinargs(struct ps_prochandle *P, int nargs, argdes_t *argp, 473 uintptr_t ap) 474 { 475 uint32_t arglist32[MAXARGS+2]; 476 uint64_t arglist64[MAXARGS+2]; 477 int i; 478 argdes_t *adp; 479 int model = P->status.pr_dmodel; 480 481 for (i = 0, adp = argp; i < nargs; i++, adp++) { 482 arglist32[i] = (uint32_t)adp->arg_value; 483 arglist64[i] = (uint64_t)adp->arg_value; 484 485 if (i < 6) 486 (void) Pputareg(P, R_O0+i, adp->arg_value); 487 } 488 489 if (model == PR_MODEL_LP64) { 490 if (nargs > 6 && 491 Pwrite(P, &arglist64[0], sizeof (int64_t) * nargs, 492 (uintptr_t)ap) != sizeof (int64_t) * nargs) 493 return (-1); 494 } else { 495 if (nargs > 6 && 496 Pwrite(P, &arglist32[0], sizeof (int32_t) * nargs, 497 (uintptr_t)ap) != sizeof (int32_t) * nargs) 498 return (-1); 499 } 500 501 return (0); 502 } 503 504 /* ARGSUSED */ 505 int 506 Psyscall_copyoutargs(struct ps_prochandle *P, int nargs, argdes_t *argp, 507 uintptr_t ap) 508 { 509 /* Do nothing */ 510 return (0); 511 } 512