xref: /illumos-gate/usr/src/lib/libproc/amd64/Pisadep.c (revision d9452f23)
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 static uchar_t syscall_instr[] = { 0x0f, 0x05 };
44 
45 const char *
46 Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr)
47 {
48 	map_info_t *mp = Paddr2mptr(P, pltaddr);
49 	file_info_t *fp;
50 	size_t i;
51 	uintptr_t r_addr;
52 
53 	if (mp == NULL || (fp = mp->map_file) == NULL ||
54 	    fp->file_plt_base == 0 ||
55 	    pltaddr - fp->file_plt_base >= fp->file_plt_size) {
56 		errno = EINVAL;
57 		return (NULL);
58 	}
59 
60 	i = (pltaddr - fp->file_plt_base) / M_PLT_ENTSIZE - M_PLT_XNumber;
61 
62 	if (P->status.pr_dmodel == PR_MODEL_LP64) {
63 		Elf64_Rela r;
64 
65 		r_addr = fp->file_jmp_rel + i * sizeof (r);
66 
67 		if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
68 		    (i = ELF64_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
69 			Elf_Data *data = fp->file_dynsym.sym_data_pri;
70 			Elf64_Sym *symp = &(((Elf64_Sym *)data->d_buf)[i]);
71 
72 			return (fp->file_dynsym.sym_strs + symp->st_name);
73 		}
74 	} else {
75 		Elf32_Rel r;
76 
77 		r_addr = fp->file_jmp_rel + i * sizeof (r);
78 
79 		if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&
80 		    (i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {
81 			Elf_Data *data = fp->file_dynsym.sym_data_pri;
82 			Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);
83 
84 			return (fp->file_dynsym.sym_strs + symp->st_name);
85 		}
86 	}
87 
88 	return (NULL);
89 }
90 
91 int
92 Pissyscall(struct ps_prochandle *P, uintptr_t addr)
93 {
94 	uchar_t instr[16];
95 
96 	if (P->status.pr_dmodel == PR_MODEL_LP64) {
97 		if (Pread(P, instr, sizeof (syscall_instr), addr) !=
98 		    sizeof (syscall_instr) ||
99 		    memcmp(instr, syscall_instr, sizeof (syscall_instr)) != 0)
100 			return (0);
101 		else
102 			return (1);
103 	}
104 
105 	if (Pread(P, instr, sizeof (int_syscall_instr), addr) !=
106 	    sizeof (int_syscall_instr))
107 		return (0);
108 
109 	if (memcmp(instr, int_syscall_instr, sizeof (int_syscall_instr)) == 0)
110 		return (1);
111 
112 	return (0);
113 }
114 
115 int
116 Pissyscall_prev(struct ps_prochandle *P, uintptr_t addr, uintptr_t *dst)
117 {
118 	int ret;
119 
120 	if (P->status.pr_dmodel == PR_MODEL_LP64) {
121 		if (Pissyscall(P, addr - sizeof (syscall_instr))) {
122 			if (dst)
123 				*dst = addr - sizeof (syscall_instr);
124 			return (1);
125 		}
126 		return (0);
127 	}
128 
129 	if ((ret = Pissyscall(P, addr - sizeof (int_syscall_instr))) != 0) {
130 		if (dst)
131 			*dst = addr - sizeof (int_syscall_instr);
132 		return (ret);
133 	}
134 
135 	return (0);
136 }
137 
138 int
139 Pissyscall_text(struct ps_prochandle *P, const void *buf, size_t buflen)
140 {
141 	if (P->status.pr_dmodel == PR_MODEL_LP64) {
142 		if (buflen >= sizeof (syscall_instr) &&
143 		    memcmp(buf, syscall_instr, sizeof (syscall_instr)) == 0)
144 			return (1);
145 		else
146 			return (0);
147 	}
148 
149 	if (buflen < sizeof (int_syscall_instr))
150 		return (0);
151 
152 	if (memcmp(buf, int_syscall_instr, sizeof (int_syscall_instr)) == 0)
153 		return (1);
154 
155 	return (0);
156 }
157 
158 #define	TR_ARG_MAX 6	/* Max args to print, same as SPARC */
159 
160 /*
161  * Given a return address, determine the likely number of arguments
162  * that were pushed on the stack prior to its execution.  We do this by
163  * expecting that a typical call sequence consists of pushing arguments on
164  * the stack, executing a call instruction, and then performing an add
165  * on %esp to restore it to the value prior to pushing the arguments for
166  * the call.  We attempt to detect such an add, and divide the addend
167  * by the size of a word to determine the number of pushed arguments.
168  *
169  * If we do not find such an add, this does not necessarily imply that the
170  * function took no arguments. It is not possible to reliably detect such a
171  * void function because hand-coded assembler does not always perform an add
172  * to %esp immediately after the "call" instruction (eg. _sys_call()).
173  * Because of this, we default to returning MIN(sz, TR_ARG_MAX) instead of 0
174  * in the absence of an add to %esp.
175  */
176 static ulong_t
177 argcount(struct ps_prochandle *P, uint32_t pc, ssize_t sz)
178 {
179 	uchar_t instr[6];
180 	ulong_t count, max;
181 
182 	max = MIN(sz / sizeof (uint32_t), TR_ARG_MAX);
183 
184 	/*
185 	 * Read the instruction at the return location.
186 	 */
187 	if (Pread(P, instr, sizeof (instr), (uintptr_t)pc) != sizeof (instr))
188 		return (max);
189 
190 	if (instr[1] != 0xc4)
191 		return (max);
192 
193 	switch (instr[0]) {
194 	case 0x81:	/* count is a longword */
195 		count = instr[2]+(instr[3]<<8)+(instr[4]<<16)+(instr[5]<<24);
196 		break;
197 	case 0x83:	/* count is a byte */
198 		count = instr[2];
199 		break;
200 	default:
201 		return (max);
202 	}
203 
204 	count /= sizeof (uint32_t);
205 	return (MIN(count, max));
206 }
207 
208 static void
209 ucontext_32_to_prgregs(const ucontext32_t *uc, prgregset_t dst)
210 {
211 	const greg32_t *src = &uc->uc_mcontext.gregs[0];
212 
213 	dst[REG_DS] = (uint16_t)src[DS];
214 	dst[REG_ES] = (uint16_t)src[ES];
215 
216 	dst[REG_GS] = (uint16_t)src[GS];
217 	dst[REG_FS] = (uint16_t)src[FS];
218 	dst[REG_SS] = (uint16_t)src[SS];
219 	dst[REG_RSP] = (uint32_t)src[UESP];
220 	dst[REG_RFL] = src[EFL];
221 	dst[REG_CS] = (uint16_t)src[CS];
222 	dst[REG_RIP] = (uint32_t)src[EIP];
223 	dst[REG_ERR] = (uint32_t)src[ERR];
224 	dst[REG_TRAPNO] = (uint32_t)src[TRAPNO];
225 	dst[REG_RAX] = (uint32_t)src[EAX];
226 	dst[REG_RCX] = (uint32_t)src[ECX];
227 	dst[REG_RDX] = (uint32_t)src[EDX];
228 	dst[REG_RBX] = (uint32_t)src[EBX];
229 	dst[REG_RBP] = (uint32_t)src[EBP];
230 	dst[REG_RSI] = (uint32_t)src[ESI];
231 	dst[REG_RDI] = (uint32_t)src[EDI];
232 }
233 
234 static int
235 Pstack_iter32(struct ps_prochandle *P, const prgregset_t regs,
236     proc_stack_f *func, void *arg)
237 {
238 	prgreg_t *prevfp = NULL;
239 	uint_t pfpsize = 0;
240 	int nfp = 0;
241 	struct {
242 		prgreg32_t fp;
243 		prgreg32_t pc;
244 		prgreg32_t args[32];
245 	} frame;
246 	uint_t argc;
247 	ssize_t sz;
248 	prgregset_t gregs;
249 	uint32_t fp, pfp, pc;
250 	long args[32];
251 	int rv;
252 	int i;
253 
254 	/*
255 	 * Type definition for a structure corresponding to an IA32
256 	 * signal frame.  Refer to the comments in Pstack.c for more info
257 	 */
258 	typedef struct {
259 		prgreg32_t fp;
260 		prgreg32_t pc;
261 		int signo;
262 		caddr32_t ucp;
263 		caddr32_t sip;
264 	} sf_t;
265 
266 	uclist_t ucl;
267 	ucontext32_t uc;
268 	uintptr_t uc_addr;
269 
270 	init_uclist(&ucl, P);
271 	(void) memcpy(gregs, regs, sizeof (gregs));
272 
273 	fp = regs[R_FP];
274 	pc = regs[R_PC];
275 
276 	while (fp != 0 || pc != 0) {
277 		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))
278 			break;
279 
280 		if (fp != 0 &&
281 		    (sz = Pread(P, &frame, sizeof (frame), (uintptr_t)fp)
282 		    >= (ssize_t)(2* sizeof (uint32_t)))) {
283 			/*
284 			 * One more trick for signal frames: the kernel sets
285 			 * the return pc of the signal frame to 0xffffffff on
286 			 * Intel IA32, so argcount won't work.
287 			 */
288 			if (frame.pc != -1L) {
289 				sz -= 2* sizeof (uint32_t);
290 				argc = argcount(P, (uint32_t)frame.pc, sz);
291 			} else
292 				argc = 3; /* sighandler(signo, sip, ucp) */
293 		} else {
294 			(void) memset(&frame, 0, sizeof (frame));
295 			argc = 0;
296 		}
297 
298 		gregs[R_FP] = fp;
299 		gregs[R_PC] = pc;
300 
301 		for (i = 0; i < argc; i++)
302 			args[i] = (uint32_t)frame.args[i];
303 
304 		if ((rv = func(arg, gregs, argc, args)) != 0)
305 			break;
306 
307 		/*
308 		 * In order to allow iteration over java frames (which can have
309 		 * their own frame pointers), we allow the iterator to change
310 		 * the contents of gregs.  If we detect a change, then we assume
311 		 * that the new values point to the next frame.
312 		 */
313 		if (gregs[R_FP] != fp || gregs[R_PC] != pc) {
314 			fp = gregs[R_FP];
315 			pc = gregs[R_PC];
316 			continue;
317 		}
318 
319 		pfp = fp;
320 		fp = frame.fp;
321 		pc = frame.pc;
322 
323 		if (find_uclink(&ucl, pfp + sizeof (sf_t)))
324 			uc_addr = pfp + sizeof (sf_t);
325 		else
326 			uc_addr = NULL;
327 
328 		if (uc_addr != NULL &&
329 		    Pread(P, &uc, sizeof (uc), uc_addr) == sizeof (uc)) {
330 			ucontext_32_to_prgregs(&uc, gregs);
331 			fp = gregs[R_FP];
332 			pc = gregs[R_PC];
333 		}
334 	}
335 
336 	if (prevfp)
337 		free(prevfp);
338 
339 	free_uclist(&ucl);
340 	return (rv);
341 }
342 
343 static void
344 ucontext_n_to_prgregs(const ucontext_t *src, prgregset_t dst)
345 {
346 	(void) memcpy(dst, src->uc_mcontext.gregs, sizeof (gregset_t));
347 }
348 
349 
350 int
351 Pstack_iter(struct ps_prochandle *P, const prgregset_t regs,
352 	proc_stack_f *func, void *arg)
353 {
354 	struct {
355 		uintptr_t fp;
356 		uintptr_t pc;
357 	} frame;
358 
359 	uint_t pfpsize = 0;
360 	prgreg_t *prevfp = NULL;
361 	prgreg_t fp, pfp;
362 	prgreg_t pc;
363 
364 	prgregset_t gregs;
365 	int nfp = 0;
366 
367 	uclist_t ucl;
368 	int rv = 0;
369 	int argc;
370 
371 	uintptr_t uc_addr;
372 	ucontext_t uc;
373 
374 	/*
375 	 * Type definition for a structure corresponding to an IA32
376 	 * signal frame.  Refer to the comments in Pstack.c for more info
377 	 */
378 	typedef struct {
379 		prgreg_t fp;
380 		prgreg_t pc;
381 		prgreg_t signo;
382 		siginfo_t *sip;
383 	} sigframe_t;
384 	prgreg_t args[32];
385 
386 	if (P->status.pr_dmodel != PR_MODEL_LP64)
387 		return (Pstack_iter32(P, regs, func, arg));
388 
389 	init_uclist(&ucl, P);
390 	(void) memcpy(gregs, regs, sizeof (gregs));
391 
392 	fp = gregs[R_FP];
393 	pc = gregs[R_PC];
394 
395 	while (fp != 0 || pc != 0) {
396 
397 		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))
398 			break;
399 
400 		if (fp != 0 &&
401 		    Pread(P, &frame, sizeof (frame), (uintptr_t)fp) ==
402 		    sizeof (frame)) {
403 
404 			if (frame.pc != -1) {
405 				/*
406 				 * Function arguments are not available on
407 				 * amd64 without extensive DWARF processing.
408 				 */
409 				argc = 0;
410 			} else {
411 				argc = 3;
412 				args[2] = fp + sizeof (sigframe_t);
413 				if (Pread(P, &args, 2 * sizeof (prgreg_t),
414 				    fp + 2 * sizeof (prgreg_t)) !=
415 				    2 * sizeof (prgreg_t))
416 					argc = 0;
417 			}
418 		} else {
419 			(void) memset(&frame, 0, sizeof (frame));
420 			argc = 0;
421 		}
422 
423 		gregs[R_FP] = fp;
424 		gregs[R_PC] = pc;
425 
426 		if ((rv = func(arg, gregs, argc, args)) != 0)
427 			break;
428 
429 		pfp = fp;
430 		fp = frame.fp;
431 		pc = frame.pc;
432 
433 		if (pc == -1 && find_uclink(&ucl, pfp + sizeof (sigframe_t))) {
434 			uc_addr = pfp + sizeof (sigframe_t);
435 
436 			if (Pread(P, &uc, sizeof (uc), uc_addr)
437 			    == sizeof (uc)) {
438 				ucontext_n_to_prgregs(&uc, gregs);
439 				fp = gregs[R_FP];
440 				pc = gregs[R_PC];
441 			}
442 		}
443 	}
444 
445 	if (prevfp)
446 		free(prevfp);
447 
448 	free_uclist(&ucl);
449 
450 	return (rv);
451 }
452 
453 uintptr_t
454 Psyscall_setup(struct ps_prochandle *P, int nargs, int sysindex, uintptr_t sp)
455 {
456 	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
457 		sp -= sizeof (int) * (nargs+2);
458 
459 		P->status.pr_lwp.pr_reg[REG_RAX] = sysindex;
460 		P->status.pr_lwp.pr_reg[REG_RSP] = sp;
461 		P->status.pr_lwp.pr_reg[REG_RIP] = P->sysaddr;
462 	} else {
463 		int pusharg = (nargs > 6) ? nargs - 6: 0;
464 
465 		sp -= sizeof (int64_t) * (pusharg+2);
466 
467 		P->status.pr_lwp.pr_reg[REG_RAX] = sysindex;
468 		P->status.pr_lwp.pr_reg[REG_RSP] = sp;
469 		P->status.pr_lwp.pr_reg[REG_RIP] = P->sysaddr;
470 	}
471 
472 	return (sp);
473 }
474 
475 int
476 Psyscall_copyinargs(struct ps_prochandle *P, int nargs, argdes_t *argp,
477     uintptr_t ap)
478 {
479 	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
480 		int32_t arglist[MAXARGS+2];
481 		int i;
482 		argdes_t *adp;
483 
484 		for (i = 0, adp = argp; i < nargs; i++, adp++)
485 			arglist[1 + i] = (int32_t)adp->arg_value;
486 
487 		arglist[0] = P->status.pr_lwp.pr_reg[REG_RIP];
488 		if (Pwrite(P, &arglist[0], sizeof (int) * (nargs+1),
489 		    (uintptr_t)ap) != sizeof (int) * (nargs+1))
490 			return (-1);
491 	} else {
492 		int64_t arglist[MAXARGS+2];
493 		int i;
494 		argdes_t *adp;
495 		int pusharg = (nargs > 6) ? nargs - 6: 0;
496 
497 		for (i = 0, adp = argp; i < nargs; i++, adp++) {
498 			switch (i) {
499 			case 0:
500 				(void) Pputareg(P, REG_RDI, adp->arg_value);
501 				break;
502 			case 1:
503 				(void) Pputareg(P, REG_RSI, adp->arg_value);
504 				break;
505 			case 2:
506 				(void) Pputareg(P, REG_RDX, adp->arg_value);
507 				break;
508 			case 3:
509 				(void) Pputareg(P, REG_RCX, adp->arg_value);
510 				break;
511 			case 4:
512 				(void) Pputareg(P, REG_R8, adp->arg_value);
513 				break;
514 			case 5:
515 				(void) Pputareg(P, REG_R9, adp->arg_value);
516 				break;
517 			default:
518 				arglist[i - 5] = (uint64_t)adp->arg_value;
519 				break;
520 			}
521 		}
522 
523 		arglist[0] = P->status.pr_lwp.pr_reg[REG_RIP];
524 
525 		if (Pwrite(P, &arglist[0],
526 		    sizeof (int64_t) * (pusharg + 1), ap) !=
527 		    sizeof (int64_t) * (pusharg + 1))
528 			return (-1);
529 	}
530 
531 	return (0);
532 }
533 
534 int
535 Psyscall_copyoutargs(struct ps_prochandle *P, int nargs, argdes_t *argp,
536     uintptr_t ap)
537 {
538 	if (P->status.pr_dmodel == PR_MODEL_ILP32) {
539 		uint32_t arglist[MAXARGS + 2];
540 		int i;
541 		argdes_t *adp;
542 
543 		if (Pread(P, &arglist[0], sizeof (int) * (nargs+1),
544 		    (uintptr_t)ap) != sizeof (int) * (nargs+1))
545 			return (-1);
546 
547 		for (i = 0, adp = argp; i < nargs; i++, adp++)
548 			adp->arg_value = arglist[i];
549 	} else {
550 		int pusharg = (nargs > 6) ? nargs - 6: 0;
551 		int64_t arglist[MAXARGS+2];
552 		int i;
553 		argdes_t *adp;
554 
555 		if (pusharg  > 0 &&
556 		    Pread(P, &arglist[0], sizeof (int64_t) * (pusharg + 1),
557 		    ap) != sizeof (int64_t) * (pusharg + 1))
558 			return (-1);
559 
560 		for (i = 0, adp = argp; i < nargs; i++, adp++) {
561 			switch (i) {
562 			case 0:
563 				adp->arg_value =
564 				    P->status.pr_lwp.pr_reg[REG_RDI];
565 				break;
566 			case 1:
567 				adp->arg_value =
568 				    P->status.pr_lwp.pr_reg[REG_RSI];
569 				break;
570 			case 2:
571 				adp->arg_value =
572 				    P->status.pr_lwp.pr_reg[REG_RDX];
573 				break;
574 			case 3:
575 				adp->arg_value =
576 				    P->status.pr_lwp.pr_reg[REG_RCX];
577 				break;
578 			case 4:
579 				adp->arg_value =
580 				    P->status.pr_lwp.pr_reg[REG_R8];
581 				break;
582 			case 5:
583 				adp->arg_value =
584 				    P->status.pr_lwp.pr_reg[REG_R9];
585 				break;
586 			default:
587 				adp->arg_value = arglist[i - 6];
588 				break;
589 			}
590 		}
591 
592 		return (0);
593 	}
594 
595 	return (0);
596 }
597