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