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 #include <sys/stack.h> 30 #include <sys/regset.h> 31 #include <sys/frame.h> 32 #include <sys/sysmacros.h> 33 #include <sys/trap.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 44 #define M_PLT_NRSV 1 /* reserved PLT entries */ 45 #define M_PLT_ENTSIZE 16 /* size of each PLT entry */ 46 47 static uchar_t int_syscall_instr[] = { 0xCD, T_SYSCALLINT }; 48 49 const char * 50 Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr) 51 { 52 map_info_t *mp = Paddr2mptr(P, pltaddr); 53 54 uintptr_t r_addr; 55 file_info_t *fp; 56 Elf32_Rel r; 57 size_t i; 58 59 if (mp == NULL || (fp = mp->map_file) == NULL || 60 fp->file_plt_base == 0 || 61 pltaddr - fp->file_plt_base >= fp->file_plt_size) { 62 errno = EINVAL; 63 return (NULL); 64 } 65 66 i = (pltaddr - fp->file_plt_base) / M_PLT_ENTSIZE - M_PLT_NRSV; 67 68 r_addr = fp->file_jmp_rel + i * sizeof (r); 69 70 if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) && 71 (i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) { 72 73 Elf_Data *data = fp->file_dynsym.sym_data; 74 Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]); 75 76 return (fp->file_dynsym.sym_strs + symp->st_name); 77 } 78 79 return (NULL); 80 } 81 82 int 83 Pissyscall(struct ps_prochandle *P, uintptr_t addr) 84 { 85 uchar_t instr[16]; 86 87 if (Pread(P, instr, sizeof (int_syscall_instr), addr) != 88 sizeof (int_syscall_instr)) 89 return (0); 90 91 if (memcmp(instr, int_syscall_instr, sizeof (int_syscall_instr)) == 0) 92 return (1); 93 94 return (0); 95 } 96 97 int 98 Pissyscall_prev(struct ps_prochandle *P, uintptr_t addr, uintptr_t *dst) 99 { 100 int ret; 101 102 if (ret = Pissyscall(P, addr - sizeof (int_syscall_instr))) { 103 if (dst) 104 *dst = addr - sizeof (int_syscall_instr); 105 return (ret); 106 } 107 108 return (0); 109 } 110 111 /* ARGSUSED */ 112 int 113 Pissyscall_text(struct ps_prochandle *P, const void *buf, size_t buflen) 114 { 115 if (buflen < sizeof (int_syscall_instr)) 116 return (0); 117 118 if (memcmp(buf, int_syscall_instr, sizeof (int_syscall_instr)) == 0) 119 return (1); 120 121 return (0); 122 } 123 124 #define TR_ARG_MAX 6 /* Max args to print, same as SPARC */ 125 126 /* 127 * Given a return address, determine the likely number of arguments 128 * that were pushed on the stack prior to its execution. We do this by 129 * expecting that a typical call sequence consists of pushing arguments on 130 * the stack, executing a call instruction, and then performing an add 131 * on %esp to restore it to the value prior to pushing the arguments for 132 * the call. We attempt to detect such an add, and divide the addend 133 * by the size of a word to determine the number of pushed arguments. 134 * 135 * If we do not find such an add, this does not necessarily imply that the 136 * function took no arguments. It is not possible to reliably detect such a 137 * void function because hand-coded assembler does not always perform an add 138 * to %esp immediately after the "call" instruction (eg. _sys_call()). 139 * Because of this, we default to returning MIN(sz, TR_ARG_MAX) instead of 0 140 * in the absence of an add to %esp. 141 */ 142 static ulong_t 143 argcount(struct ps_prochandle *P, long pc, ssize_t sz) 144 { 145 uchar_t instr[6]; 146 ulong_t count, max; 147 148 max = MIN(sz / sizeof (long), TR_ARG_MAX); 149 150 /* 151 * Read the instruction at the return location. 152 */ 153 if (Pread(P, instr, sizeof (instr), pc) != sizeof (instr) || 154 instr[1] != 0xc4) 155 return (max); 156 157 switch (instr[0]) { 158 case 0x81: /* count is a longword */ 159 count = instr[2]+(instr[3]<<8)+(instr[4]<<16)+(instr[5]<<24); 160 break; 161 case 0x83: /* count is a byte */ 162 count = instr[2]; 163 break; 164 default: 165 return (max); 166 } 167 168 count /= sizeof (long); 169 return (MIN(count, max)); 170 } 171 172 static void 173 ucontext_n_to_prgregs(const ucontext_t *src, prgregset_t dst) 174 { 175 (void) memcpy(dst, src->uc_mcontext.gregs, sizeof (gregset_t)); 176 } 177 178 int 179 Pstack_iter(struct ps_prochandle *P, const prgregset_t regs, 180 proc_stack_f *func, void *arg) 181 { 182 prgreg_t *prevfp = NULL; 183 uint_t pfpsize = 0; 184 int nfp = 0; 185 struct { 186 long fp; 187 long pc; 188 long args[32]; 189 } frame; 190 uint_t argc; 191 ssize_t sz; 192 prgregset_t gregs; 193 prgreg_t fp, pfp; 194 prgreg_t pc; 195 int rv; 196 197 /* 198 * Type definition for a structure corresponding to an IA32 199 * signal frame. Refer to the comments in Pstack.c for more info 200 */ 201 typedef struct { 202 long fp; 203 long pc; 204 int signo; 205 ucontext_t *ucp; 206 siginfo_t *sip; 207 } sf_t; 208 209 uclist_t ucl; 210 ucontext_t uc; 211 uintptr_t uc_addr; 212 213 init_uclist(&ucl, P); 214 (void) memcpy(gregs, regs, sizeof (gregs)); 215 216 fp = regs[R_FP]; 217 pc = regs[R_PC]; 218 219 while (fp != 0 || pc != 0) { 220 if (stack_loop(fp, &prevfp, &nfp, &pfpsize)) 221 break; 222 223 if (fp != 0 && 224 (sz = Pread(P, &frame, sizeof (frame), (uintptr_t)fp) 225 >= (ssize_t)(2* sizeof (long)))) { 226 /* 227 * One more trick for signal frames: the kernel sets 228 * the return pc of the signal frame to 0xffffffff on 229 * Intel IA32, so argcount won't work. 230 */ 231 if (frame.pc != -1L) { 232 sz -= 2* sizeof (long); 233 argc = argcount(P, (long)frame.pc, sz); 234 } else 235 argc = 3; /* sighandler(signo, sip, ucp) */ 236 } else { 237 (void) memset(&frame, 0, sizeof (frame)); 238 argc = 0; 239 } 240 241 gregs[R_FP] = fp; 242 gregs[R_PC] = pc; 243 244 if ((rv = func(arg, gregs, argc, frame.args)) != 0) 245 break; 246 247 /* 248 * In order to allow iteration over java frames (which can have 249 * their own frame pointers), we allow the iterator to change 250 * the contents of gregs. If we detect a change, then we assume 251 * that the new values point to the next frame. 252 */ 253 if (gregs[R_FP] != fp || gregs[R_PC] != pc) { 254 fp = gregs[R_FP]; 255 pc = gregs[R_PC]; 256 continue; 257 } 258 259 pfp = fp; 260 fp = frame.fp; 261 pc = frame.pc; 262 263 if (find_uclink(&ucl, pfp + sizeof (sf_t))) 264 uc_addr = pfp + sizeof (sf_t); 265 else 266 uc_addr = NULL; 267 268 if (uc_addr != NULL && 269 Pread(P, &uc, sizeof (uc), uc_addr) == sizeof (uc)) { 270 271 ucontext_n_to_prgregs(&uc, gregs); 272 fp = gregs[R_FP]; 273 pc = gregs[R_PC]; 274 } 275 } 276 277 if (prevfp) 278 free(prevfp); 279 280 free_uclist(&ucl); 281 return (rv); 282 } 283 284 uintptr_t 285 Psyscall_setup(struct ps_prochandle *P, int nargs, int sysindex, uintptr_t sp) 286 { 287 sp -= sizeof (int) * (nargs+2); /* space for arg list + CALL parms */ 288 289 P->status.pr_lwp.pr_reg[EAX] = sysindex; 290 P->status.pr_lwp.pr_reg[R_SP] = sp; 291 P->status.pr_lwp.pr_reg[R_PC] = P->sysaddr; 292 293 return (sp); 294 } 295 296 int 297 Psyscall_copyinargs(struct ps_prochandle *P, int nargs, argdes_t *argp, 298 uintptr_t ap) 299 { 300 int32_t arglist[MAXARGS+2]; 301 int i; 302 argdes_t *adp; 303 304 for (i = 0, adp = argp; i < nargs; i++, adp++) 305 arglist[1 + i] = (int32_t)adp->arg_value; 306 307 arglist[0] = P->status.pr_lwp.pr_reg[R_PC]; 308 if (Pwrite(P, &arglist[0], sizeof (int) * (nargs+1), 309 (uintptr_t)ap) != sizeof (int) * (nargs+1)) 310 return (-1); 311 312 return (0); 313 } 314 315 int 316 Psyscall_copyoutargs(struct ps_prochandle *P, int nargs, argdes_t *argp, 317 uintptr_t ap) 318 { 319 uint32_t arglist[MAXARGS + 2]; 320 int i; 321 argdes_t *adp; 322 323 if (Pread(P, &arglist[0], sizeof (int) * (nargs+1), (uintptr_t)ap) 324 != sizeof (int) * (nargs+1)) 325 return (-1); 326 327 for (i = 0, adp = argp; i < nargs; i++, adp++) 328 adp->arg_value = arglist[i]; 329 330 return (0); 331 } 332