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