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