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